Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions console/atest-desktop/forge.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ module.exports = {
ui: {
"enabled": true,
"chooseDirectory": true
},
beforeCreate: (msiCreator) => {
// Add installation directory to system PATH
msiCreator.wixTemplate = msiCreator.wixTemplate.replace(
'</Product>',
` <Property Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" />
<CustomAction Id="AddToPath" Property="PATH" Value="[INSTALLDIR]" Execute="immediate" />
<CustomAction Id="RemoveFromPath" Property="PATH" Value="[INSTALLDIR]" Execute="immediate" />

<InstallExecuteSequence>
<Custom Action="AddToPath" After="InstallFiles">NOT Installed</Custom>
<Custom Action="RemoveFromPath" Before="RemoveFiles">REMOVE="ALL"</Custom>
</InstallExecuteSequence>

<Component Id="PathComponent" Guid="*" Directory="INSTALLDIR">
<Environment Id="PATH" Name="PATH" Value="[INSTALLDIR]" Permanent="no" Part="last" Action="set" System="yes" />
</Component>

</Product>`
);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions docs/site/content/zh/latest/tasks/mock.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,11 @@ items:
proxies:
- path: /api/v1/{part}
target: http://atest.localhost:8080
echo: true
```

当 echo 的值为 true 时,会把收到的请求以及响应打印出来,方便观察数据。

当我们发起如下的请求时,实际请求的地址为 `http://atest.localhost:8080/api/v1/projects`

```shell
Expand Down
1 change: 1 addition & 0 deletions docs/site/content/zh/latest/tasks/mock/simple.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ proxies:
target: http://atest.localhost:8080
- path: /open-apis/bot/v2/hook/{token}
target: https://open.feishu.cn/
echo: true
requestAmend:
bodyPatch: |
[{
Expand Down
25 changes: 25 additions & 0 deletions pkg/mock/in_memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@
fmt.Println("after patch:", string(requestBody))
}

if proxy.Echo {
fmt.Println("Original request header:")
for k, v := range req.Header {
fmt.Println(k, ":", v)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

Sensitive data returned by HTTP request headers
flows to a logging call.

Copilot Autofix

AI about 2 months ago

To fix the problem, we should prevent logging sensitive HTTP headers. The best practice is to either omit logging headers entirely, or to redact/obfuscate sensitive header values before logging them. When logging headers, we should maintain a denylist of sensitive header names (e.g., Authorization, Cookie, Set-Cookie, Proxy-Authorization) and mask their values if they're present.
Specifically, in pkg/mock/in_memory.go, within the loop starting at line 183, we should update the logging so that before printing each header, we check if it is sensitive; if so, print its value as <redacted>, else print its actual value. This can be done by a simple helper function that matches header names case-insensitively.
Minimal changes are needed and no functionality should be lost (other than leaking secrets). We'll define the sensitive headers list in this code region and use it for redaction.

Suggested changeset 1
pkg/mock/in_memory.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/mock/in_memory.go b/pkg/mock/in_memory.go
--- a/pkg/mock/in_memory.go
+++ b/pkg/mock/in_memory.go
@@ -181,7 +181,11 @@
 		if proxy.Echo {
 			fmt.Println("Original request header:")
 			for k, v := range req.Header {
-				fmt.Println(k, ":", v)
+				if isSensitiveHeader(k) {
+					fmt.Println(k, ":", "<redacted>")
+				} else {
+					fmt.Println(k, ":", v)
+				}
 			}
 			fmt.Println("Original request path:", req.URL)
 			fmt.Println("Original request payload:")
@@ -226,6 +230,27 @@
 	})
 }
 
+// isSensitiveHeader returns true if the HTTP header name is considered sensitive.
+func isSensitiveHeader(headerName string) bool {
+	// List of common sensitive headers
+	sensitive := []string{
+		"Authorization",
+		"Cookie",
+		"Set-Cookie",
+		"Proxy-Authorization",
+		"X-Api-Key",
+		"X-Auth-Token",
+		"X-Csrf-Token",
+	}
+	normalized := strings.ToLower(headerName)
+	for _, h := range sensitive {
+		if normalized == strings.ToLower(h) {
+			return true
+		}
+	}
+	return false
+}
+
 func (s *inMemoryServer) tcpProxy(proxy *Proxy) {
 	fmt.Println("start to proxy", proxy.Port)
 	lisener, err := net.Listen("tcp", fmt.Sprintf(":%d", proxy.Port))
EOF
@@ -181,7 +181,11 @@
if proxy.Echo {
fmt.Println("Original request header:")
for k, v := range req.Header {
fmt.Println(k, ":", v)
if isSensitiveHeader(k) {
fmt.Println(k, ":", "<redacted>")
} else {
fmt.Println(k, ":", v)
}
}
fmt.Println("Original request path:", req.URL)
fmt.Println("Original request payload:")
@@ -226,6 +230,27 @@
})
}

// isSensitiveHeader returns true if the HTTP header name is considered sensitive.
func isSensitiveHeader(headerName string) bool {
// List of common sensitive headers
sensitive := []string{
"Authorization",
"Cookie",
"Set-Cookie",
"Proxy-Authorization",
"X-Api-Key",
"X-Auth-Token",
"X-Csrf-Token",
}
normalized := strings.ToLower(headerName)
for _, h := range sensitive {
if normalized == strings.ToLower(h) {
return true
}
}
return false
}

func (s *inMemoryServer) tcpProxy(proxy *Proxy) {
fmt.Println("start to proxy", proxy.Port)
lisener, err := net.Listen("tcp", fmt.Sprintf(":%d", proxy.Port))
Copilot is powered by AI and may make mistakes. Always verify output.
}
fmt.Println("Original request path:", req.URL)
fmt.Println("Original request payload:")
fmt.Println(string(requestBody))

Check notice

Code scanning / SonarCloud

Logging should not be vulnerable to injection attacks Low

Change this code to not log user-controlled data. See more on SonarQube Cloud
}

targetReq, err := http.NewRequestWithContext(req.Context(), req.Method, api, bytes.NewBuffer(requestBody))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
Expand Down Expand Up @@ -206,6 +216,12 @@
for k, v := range resp.Header {
w.Header().Add(k, v[0])
}

if proxy.Echo {
fmt.Println("Original response payload:")
fmt.Println(string(data))
}

w.Write(data)
})
}
Expand Down Expand Up @@ -580,6 +596,15 @@
}
}

if wh.Request.BodyFromFile != "" {
if data, readErr := os.ReadFile(wh.Request.BodyFromFile); readErr != nil {
memLogger.Error(readErr, "failed to read file", "file", wh.Request.BodyFromFile)
return
} else {
wh.Request.Body = string(data)
}
}

var payload io.Reader
payload, err = render.RenderAsReader("mock webhook server payload", wh.Request.Body, wh)
if err != nil {
Expand Down
12 changes: 7 additions & 5 deletions pkg/mock/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ type Item struct {
}

type Request struct {
Protocol string `yaml:"protocol" json:"protocol"`
Path string `yaml:"path" json:"path"`
Method string `yaml:"method" json:"method"`
Header map[string]string `yaml:"header" json:"header"`
Body string `yaml:"body" json:"body"`
Protocol string `yaml:"protocol" json:"protocol"`
Path string `yaml:"path" json:"path"`
Method string `yaml:"method" json:"method"`
Header map[string]string `yaml:"header" json:"header"`
Body string `yaml:"body" json:"body"`
BodyFromFile string `yaml:"bodyFromFile" json:"bodyFromFile"`
}

type RequestWithAuth struct {
Expand Down Expand Up @@ -66,6 +67,7 @@ type Proxy struct {
Target string `yaml:"target" json:"target"`
RequestAmend RequestAmend `yaml:"requestAmend" json:"requestAmend"`
Protocol string `yaml:"protocol" json:"protocol"`
Echo bool `yaml:"echo" json:"echo"`
}

type RequestAmend struct {
Expand Down
Loading