Repository: microsoft/ApplicationInsights-node.js (ts)

Issue:
PII Leak: Stack parsing is broken in scoped npm packages
My package is @react-native-windows/cli . When an exception is thrown from inside of one of our tools, the EnvelopeFactory tries parsing the stack into a parsedStack : StackFrame[]
However the regex used doesn't work for packages (or file paths) that have an @ sign in the name:
https://github.com/microsoft/ApplicationInsights-node.js/blob/develop/Library/EnvelopeFactory.ts#L306-L313

The regex is `/^([\s]+at)?(.*?)(\@|\s\(|\s)([^\(\@\n]+):([0-9]+):([0-9]+)(\)?)$/`
I'm throwing an exception from a lambda so there is no method name. The stack string looks like:
```
Error: solutionFile invalid. Error: Too many app solution files found, please specify in react-native.config.
    at E:\rnw\packages\@react-native-windows\cli\lib-commonjs\runWindows\utils\autolink.js:131:23
    at Array.forEach (<anonymous>)
    at Object.updateAutoLink [as func] (E:\rnw\packages\@react-native-windows\cli\lib-commonjs\runWindows\utils\autolink.js:125:24)
    at runWindowsInternal (E:\rnw\packages\@react-native-windows\cli\lib-commonjs\runWindows\runWindows.js:204:42)
    at Object.runWindows [as func] (E:\rnw\packages\@react-native-windows\cli\lib-commonjs\runWindows\runWindows.js:139:15)
    at Command.handleAction (E:\test63\node_modules\@react-native-community\cli\build\index.js:186:23)
    at Command.listener (E:\test63\node_modules\commander\index.js:315:8)
    at Command.emit (events.js:209:13)
    at Command.parseArgs (E:\test63\node_modules\commander\index.js:651:12)
    at Command.parse (E:\test63\node_modules\commander\index.js:474:21)
```

When parseStack tries the second line, it finds a match:
![image](https://user-images.githubusercontent.com/22989529/97935677-21efd900-1d2e-11eb-91a9-6a8b1ed79b1c.png)

This ends up putting the path as part of the method name. 
This causes a potential PII leak since file path information is being exposed through a method name which is not expected to have any PII.

Pull request:
fix stackframe regex on scoped packages
Updates regex to support stackframes from scoped packages, e.g. `@microsoft/applicationinsights-web`

Fixes #695 

Patch:
diff --git a/Library/EnvelopeFactory.ts b/Library/EnvelopeFactory.ts
index 7cd499f..7940367 100644
--- a/Library/EnvelopeFactory.ts
+++ b/Library/EnvelopeFactory.ts
@@ -356,7 +356,7 @@ class _StackFrame {
 
     // regex to match stack frames from ie/chrome/ff
     // methodName=$2, fileName=$4, lineNo=$5, column=$6
-    public static regex = /^([\s]+at)?(.*?)(\@|\s\(|\s)([^\(\@\n]+):([0-9]+):([0-9]+)(\)?)$/;
+    public static regex = /^(\s+at)?(.*?)(\@|\s\(|\s)([^\(\n]+):(\d+):(\d+)(\)?)$/;
     public static baseSize = 58; //'{"method":"","level":,"assembly":"","fileName":"","line":}'.length
     public sizeInBytes = 0;
     public level: number;


Test patch:
diff --git a/Tests/Library/EnvelopeFactoryTests.ts b/Tests/Library/EnvelopeFactoryTests.ts
index e8bb1b0..35d8e82 100644
--- a/Tests/Library/EnvelopeFactoryTests.ts
+++ b/Tests/Library/EnvelopeFactoryTests.ts
@@ -107,6 +107,42 @@ describe("Library/EnvelopeFactory", () => {
 
             assert.deepEqual(actual, expected);
         });
+        
+        it("fills stack when provided a scoped package", () => {
+            simpleError.stack = "  at Context.foo (C:/@foo/bar/example.js:123:45)\n" + simpleError.stack;
+            
+            var envelope = EnvelopeFactory.createEnvelope(<Contracts.ExceptionTelemetry>{ exception: simpleError }, Contracts.TelemetryType.Exception);
+            var exceptionData = <Contracts.Data<Contracts.ExceptionData>>envelope.data;
+
+            var actual = exceptionData.baseData.exceptions[0].parsedStack[0];
+
+            assert.deepEqual(actual, {
+                fileName: "C:/@foo/bar/example.js",
+                line: 123,
+                level: 0,
+                sizeInBytes: 141,
+                assembly: "at Context.foo (C:/@foo/bar/example.js:123:45)",
+                method: "Context.foo"
+            });
+        });
+        
+        it("fills stack when provided a scoped package", () => {
+            simpleError.stack = "  at C:/@foo/bar/example.js:123:45\n" + simpleError.stack;
+            
+            var envelope = EnvelopeFactory.createEnvelope(<Contracts.ExceptionTelemetry>{ exception: simpleError }, Contracts.TelemetryType.Exception);
+            var exceptionData = <Contracts.Data<Contracts.ExceptionData>>envelope.data;
+
+            var actual = exceptionData.baseData.exceptions[0].parsedStack[0];
+
+            assert.deepEqual(actual, {
+                fileName: "C:/@foo/bar/example.js",
+                line: 123,
+                level: 0,
+                sizeInBytes: 127,
+                assembly: "at C:/@foo/bar/example.js:123:45",
+                method: "<no_method>"
+            });
+        });
 
         it("fills 'severityLevel' with Error when not specified", () => {
             var envelope = EnvelopeFactory.createEnvelope(<Contracts.ExceptionTelemetry>{ exception: simpleError }, Contracts.TelemetryType.Exception);