Dev.to · 2 min read

I pointed my own security tool at my own GitHub Action. It found two bugs.

I pointed my own security tool at my own GitHub Action. It found two bugs.

I write an application-security tool called SecHelix. Last week I added a GitHub Action to it. Before merging, I pointed the tool at its own new Action. It found two real defects. Neither would have failed a test. Both were the kind of thing I would have shipped. This is a post about those two bugs, because they are better arguments for evidence-first review than anything I could write about the methodology. Bug one: the artifact was the wrong copy The Action runs an audit and uploads the result as a build artifact so you can download it from the workflow run. The step looked like this: - run: sechelix audit "$PATH" --json > sechelix-run.json - uses: actions/upload-artifact@... with: path: sechelix-run.json Obvious. Works. Ships. Here is what I had forgotten about my own codebase. The runner writes two copies of every result. The one it persists to disk goes through storage.write_json, which runs the payload through a redactor. The one --json prints to stdout is result.to_dict(), raw. I only had to run the redactor against a payload to see it: persisted (storage.write_json): "authorization": "[REDACTED]" stdout (audit --json): "authorization": "Bearer sk-live-abc123" So the Action was uploading the unredacted projection into a build artifact that anyone with read access to the repository can download, for the seven days it lives. During a security review, of all things — the exact run most likely to have a secret quoted in a node payload, because that is what it was looking for. The fix is one line: re-read the persisted copy with sechelix report --format json before uploading anything. The interesting part is not the fix. It is that there were two projections of the same object with different safety properties, and only one of them was documented as redacted. No test could have caught this, because both projections were behaving exactly as written. The defect was in the seam. Bug two: an output value could forge another output GitHub Actions steps communicate through a file: echo "outcome=BLOCKED" >> "$GITHUB_OUTPUT" It is newline-delimited. So a value containing a newline writes a second key. And when a key appears twice, the runner takes the last one. Which means a value like this: RUN-X outcome=PASS blocking-count=0 produces: outcome=BLOCKED reason=1 verified finding(s) at CRITICAL or HIGH severity are open. run-id=RUN-X outcome=PASS

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Programming & Dev News