Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions .github/workflows/codeant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CodeAnt CI Scan

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read
pull-requests: write

jobs:
codeant_scan:
name: Run CodeAnt CI scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Run CodeAnt CI Scan
uses: CodeAnt-AI/codeant-ci-scan-action@82f83c97a923b626244fdbf9b749ae37308eaf9e # v0.0.5
with:
access_token: ${{ secrets.CODEANT_API_TOKEN }}
1 change: 1 addition & 0 deletions .github/workflows/gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
with:
version: 2026.9.12

# nosemgrep: yaml.github-actions.security.pull-request-target-code-checkout.pull-request-target-code-checkout -- reviewed: the scanner only reads these files (rg, sed, git ls-files) and never runs them; see the note at the top.
- name: Check out the code under review
if: github.event_name == 'pull_request_target'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
name: Semgrep
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
image: semgrep/semgrep:1.178.0@sha256:32e459968daabe7ab86968184a29109b9564aa00392401156f9788452b42786b

steps:
- name: Checkout code
Expand All @@ -37,6 +37,6 @@ jobs:
- name: Upload SARIF
# if fork PR, don't upload their SARIF
if: steps.semgrep.outcome == 'success' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
uses: github/codeql-action/upload-sarif@9fddc16f0de775b9edd8a84dd5839ac2db070f8b
uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
with:
sarif_file: semgrep.sarif
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,19 @@ mise run setup # dev dependencies and git hooks
mise run check # shellcheck, shfmt check and the bats tests: what CI runs
```

`mise run` lists every task. The git hooks run the same checks before each commit. CI in [`.github/workflows/`](.github/workflows/) runs the checks and tests, this repository's own security gate, a gitleaks secret scan, Semgrep and dependency review. Releases: [docs/RELEASING.md](docs/RELEASING.md). Changes: each package's `CHANGELOG.md`.
`mise run` lists every task. The git hooks run the same checks before each commit. CI in [`.github/workflows/`](.github/workflows/) runs the checks and tests, this repository's own security gate (`mise run gate`), a gitleaks secret scan, Semgrep, dependency review, and CodeAnt AI scan. Releases: [docs/RELEASING.md](docs/RELEASING.md). Changes: each package's `CHANGELOG.md`.

## Semgrep

[`secure-semgrep`](apps/secure-semgrep/README.md) is the repository's static-analysis pack: bundled, owned rules for AI agents and bash, plus Semgrep loadout packs you can point at any codebase. It lives in [`apps/secure-semgrep`](apps/secure-semgrep/README.md) and publishes to npm as `secure-semgrep`, mirroring how `am-i-hacked` is published.

Run it over this repository (review mode records findings without breaking the build):

```bash
$ mise run semgrep
```

To turn findings into a hard gate, run `mise run semgrep-strict`. In any other repository, use it the same way as a post-`npm install` script — see the [package README](apps/secure-semgrep/README.md) for loadouts (`react`, `ts`, `node`, `py`, `rust`) and CI snippets.

## Contributing, security and support

Expand Down
18 changes: 18 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Roadmap

This is a plan, not a promise. Items can change, slip or be dropped. There are no dates: a release ships when it is ready. Anything that is neither listed here nor filed as an issue is not scheduled.

Current release: **2.0.1**.

## How releases work

- Every fix that merges ships as the next patch release: 2.0.2, then 2.0.3, and so on.
- Issues labeled `release-blocker` gate the next minor release. 2.1.0 ships once every issue with that label is closed.

## 2.1.0 candidates

A minor release that widens what the scanner reads and adds an opt-in feature.

- **Scan gitignored files by default**, with flags to skip gitignored files and to skip hidden files.
- **Full dependency scans** behind a flag (`node_modules` and similar). Scanning dependencies is slower, so it is not the default.
- **`hooks install`**, an optional sub-command that sets up a shell hook which logs the commands run in a terminal. It is opt-in: nothing touches your shell unless you run the command. Logs go to the current folder by default, with an option to choose another destination.
19 changes: 19 additions & 0 deletions apps/am-i-hacked/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@

Newest first. Default-behavior changes are marked **CHANGED**.

## 2.0.1 - 2026-10-01

**BLUF:** A security release. The scan no longer trusts the tree it is reviewing: a scanned repo's `.git/config` could make it run a command, and payloads in dot-directories, in folders named in `.ignore` or `.rgignore`, in tracked files matched by `.gitignore`, and in tracked build output were not read. It also fixes a skip on extensionless scripts.

### Security
- **CHANGED:** the scan now reads dot-directories, no longer reads `.ignore` or `.rgignore`, and scans tracked files that `.gitignore` matches. Committed build output is now scanned, so findings may appear in `dist/`, `.github/`, `.vscode/` and similar. Untracked build output listed in `.gitignore` is still skipped, and `node_modules` and `.git` are always skipped.
- Payloads were not scanned when they sat in a dot-directory, in a folder named in `.ignore` or `.rgignore`, in a tracked file matched by `.gitignore`, or in a tracked build output folder. All of these are scanned now.
- A scanned repo's `.git/config` could make the scan run a command: `git ls-files` runs any `core.fsmonitor` hook the config names. The scan now runs git with `core.fsmonitor=false`.
- **CHANGED:** 71 official Yarn releases in `.yarn/releases` are verified by SHA256 checksum; a mismatch is a finding at line 1. Unverified or malicious Yarn files no longer pass silently.

### Changed
- **CHANGED:** bundled code (webpack/esbuild/ncc) identified by markers in the first 4096 bytes (`__webpack_require__`, `__nccwpck_require__`, `webpackBootstrap`, `__toESM(`, `__commonJS(`) receives only high-signal checks. Routine patterns in bundles (dynamic code execution, network modules, child process) are counted but not flagged; obfuscation, capture/exfiltration and bot tokens still are.
- **CHANGED:** embedded WebAssembly data: URLs (`data:application/(wasm|octet-stream);base64,AGFzbQ...`) on a single line are no longer flagged for line length, as they are expected to be long.

### Fixed
- An extensionless script inside a folder with a dot in its name (for example `.devcontainer/sync-agent`) was skipped. The extensionless check now tests the file name.

Upgrade: `pnpm add -D [email protected]`, or run the pinned version without installing: `pnpx [email protected] .`

## 2.0.0 - 2026-10-01

**BLUF:** Renamed from `am-i-compromised` to `am-i-hacked`. The old command name still works. This is the first release that includes the host audit, `safe-pull` and the clipboard-stealer checks.
Expand Down
17 changes: 12 additions & 5 deletions apps/am-i-hacked/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ Linuxbrew locations, and otherwise tells you what to install (for example `brew
Install `rg` and `jq`
with `brew install ripgrep jq` or `apt-get install ripgrep jq`.

## 🔒 Privacy

The scanner runs entirely on your machine and sends nothing anywhere. The project scan and host audit make no network calls; the source is open under MIT, so anyone can verify this. Findings stay in your terminal — it is safe to run on private or sensitive code.

The package installs these commands:

| Command | What it runs |
Expand Down Expand Up @@ -144,8 +148,10 @@ The package installs these commands:
[below](#clipboardkeyloggerexfil-detection)
- Environment files (`.env`, `.env.*`) tracked in the git index

It scans JS/TS/Python/Rust/Ruby/C/C++/C# sources out of the box and skips `node_modules`, build
output and VCS dirs. Where a bare regex would be noisy it wants context: a decode call only
It scans JS/TS/Python/Rust/Ruby/C/C++/C# sources out of the box and skips `node_modules` and VCS
dirs. Build output (bundled code from webpack, esbuild, or ncc) is scanned when committed; untracked build output that `.gitignore` lists is skipped. **In bundled code, only high-signal patterns are reported as findings** — dynamic code execution and network-access patterns routine in minified code are tracked but not flagged; string-table obfuscation, capture/exfiltration and bot tokens still are.

Official Yarn releases in `.yarn/releases` are verified by SHA256 checksum against a table of 71 official releases instead of content-scanned; a mismatch fails. Where a bare regex would be noisy it wants context: a decode call only
trips near an execution call or a long literal, and a lone ANSI color escape is not a payload.

## 🖥️ Host audit
Expand Down Expand Up @@ -273,9 +279,10 @@ a shebang.
| Persistence beside capture | `launchctl load`, `~/Library/LaunchAgents`, `crontab -`, `~/.config/autostart` in a script that also captures | Persistence installed by a script that captures input |
| Capture-shaped file name | name matching `(clip\|key\|screen)[-_ ]?(logger\|monitor\|spy\|grab)` that reads the clipboard or input | Capture-named script reads the clipboard or input |

Files under `node_modules`/`.cache`, build output, and the fixtures dir are
never scanned, so a README mention or a vendor's own clipboard-library source
with no exfiltration endpoint does not trip the scan. Reviewed matches can still
Files under `node_modules` and the fixtures dir are never scanned. Untracked
build output that `.gitignore` lists is skipped too, so a README mention or a
vendor's clipboard-library source with no exfiltration endpoint does not trip
the scan. Reviewed matches can still
be marked safe with `am-i-hacked-ignore:` (see above).

`am-i-hacked host` audits the machine itself for the persistence side of this
Expand Down
Loading
Loading