By Momenul Ahmad, Founder and Lead Architect, SEOSiri. Last updated: October 2026.
A polyglot code audit means proving that every language in your project (Python, TypeScript, React, Java, Go, C, HTML) passes the same release gates: syntax and type checks, tests, static security analysis (SAST), dependency and secret scans, concurrency checks, and a tamper-evident evidence report. A bash testing pipeline is the common layer that lets one script run all of them, locally in Git Bash or in any CI runner. This guide uses SmartTransit AI, a chip-agnostic transit platform, as a worked example, and it applies equally to any system you build.
- Who this guide is for
- What "audit and testing fulfillment" means at the end of a development loop
- Worked example: SmartTransit AI
- The universal bash audit script
- Language-by-language commands
- Deep dive: audit settings that matter in each language
- Sample audit report: what a real run looks like
- How to decide pass or fail
- Troubleshooting common audit script problems
- A practical maturity path for solo builders and small teams
- Key terms in plain language
- Most advanced audit and testing tools
- Wiring the script into CI
- Mapping audit gates to industry standards
- Common mistakes
- Frequently asked questions
- Conclusion: finish the loop with evidence
- Related resources
1. Who this guide is for
This article is written for solo builders, vibe-coders who need to finish and harden a project, startup CTOs, DevOps and QA engineers, security reviewers, and agencies delivering AI-assisted software to clients. If you ask "how do I test and audit a project that mixes several languages from one terminal?", this is the answer. Platforms covered: Windows (Git Bash), macOS, Linux, GitHub Actions and any container-based CI.
2. What "audit and testing fulfillment" means at the end of a development loop
A closed development loop runs plan, build, test, fix, repeat. It is complete only when evidence shows that the requirements were met. Testing answers "does it work?" Auditing answers "can we prove it works safely, and can someone else verify that proof?" Both are needed before release. Related reading: why vibe coding projects stall and how to finish them and how accurate vibe coding tools really are.
The six release gates
| Gate | Question answered | Typical evidence |
|---|---|---|
| 1. Inventory | What languages and files are actually in scope? | File counts per language, lockfiles present |
| 2. Build and type safety | Does everything compile and type-check? | Zero errors from compiler or type checker |
| 3. Automated tests | Does behavior match requirements? | Unit, integration and protocol test results |
| 4. Security analysis | Any known vulnerable code, packages or leaked secrets? | SAST, dependency and secret scan reports |
| 5. Runtime stress | Does it hold under concurrency and load? | Race detector output, load test latency |
| 6. Evidence seal | Can a third party verify the results? | Timestamped report plus SHA-256 checksum |
3. Worked example: SmartTransit AI
SmartTransit AI is a typical multi-layer agentic system. Each layer has its own failure modes, so each gets its own gate toolchain. The architecture is explained in the chip-agnostic smart transit AI architecture guide.
| Layer | Language | Main audit focus |
|---|---|---|
| Edge firmware (vehicle unit) | C99 or Rust | Memory safety, no heap in the control loop, buffer bounds |
| Agent and MCP tool servers | Python, TypeScript | JSON-RPC 2.0 compliance, input validation, tool-call safety |
| Event pipeline and APIs | Java or Go | Thread safety, connection pools, circuit breakers |
| Operator dashboard | React, TypeScript, HTML | Type safety, CSP, accessibility, dependency risk |
4. The universal bash audit script
Save as master_polyglot_audit.sh in the repository root and run bash master_polyglot_audit.sh in Git Bash, Linux or macOS. It detects what exists, runs only the matching tools, records every result, and returns a non-zero exit code if any gate fails, which makes it safe to use as a CI gate.
#!/usr/bin/env bash
# Universal polyglot audit: Python, TS/React, Java, Go, C, HTML
set -uo pipefail
REPORT="audit-report-$(date -u +%Y%m%dT%H%M%SZ).txt"
PASS=0; FAIL=0; SKIP=0
log() { echo "$*" | tee -a "$REPORT"; }
has() { command -v "$1" >/dev/null 2>&1; }
count(){ find . -type f \( "$@" \) -not -path '*/node_modules/*' \
-not -path '*/.git/*' -not -path '*/.venv/*' | wc -l | tr -d ' '; }
run() { local name="$1"; shift
if "$@" >>"$REPORT" 2>&1; then log "[PASS] $name"; PASS=$((PASS+1))
else log "[FAIL] $name"; FAIL=$((FAIL+1)); fi; }
skip() { log "[SKIP] $1"; SKIP=$((SKIP+1)); }
log "== GATE 1: INVENTORY =="
PY=$(count -name '*.py'); TS=$(count -name '*.ts' -o -name '*.tsx')
JV=$(count -name '*.java'); GO=$(count -name '*.go')
CC=$(count -name '*.c' -o -name '*.h'); HT=$(count -name '*.html')
log "py=$PY ts=$TS java=$JV go=$GO c=$CC html=$HT"
log "== GATE 2-4: BUILD, TEST, SECURITY (per language) =="
if [ "$PY" -gt 0 ]; then
has python3 && run "python compile" python3 -m compileall -q . || skip "python3 missing"
has bandit && run "python SAST (bandit)" bandit -r . -ll -q -x ./node_modules,./.venv || skip "bandit missing"
has pytest && run "python tests" pytest -q || skip "pytest missing"
has pip-audit && run "python deps" pip-audit || skip "pip-audit missing"
fi
if [ -f package.json ]; then
[ -f tsconfig.json ] && run "typescript types" npx --no-install tsc --noEmit
run "js/ts lint" npx --no-install eslint .
run "npm deps (high+)" npm audit --audit-level=high
grep -q '"test"' package.json && run "js/ts tests" npm test --silent
fi
if [ "$GO" -gt 0 ]; then
has go && { run "go vet" go vet ./...; run "go tests + race detector" go test -race ./...; } || skip "go missing"
has gosec && run "go SAST (gosec)" gosec -quiet ./... || skip "gosec missing"
fi
if [ "$JV" -gt 0 ]; then
if [ -f pom.xml ]; then run "java build+tests (maven)" mvn -q verify
elif [ -f gradlew ]; then run "java build+tests (gradle)" ./gradlew check
else skip "no maven/gradle build file"; fi
fi
if [ "$CC" -gt 0 ]; then
has cppcheck && run "c static analysis" cppcheck --error-exitcode=1 --enable=warning,portability -q . || skip "cppcheck missing"
fi
if [ "$HT" -gt 0 ]; then
run "html validation" npx --yes html-validate "**/*.html"
fi
has gitleaks && run "secret scan" gitleaks detect --no-banner || skip "gitleaks missing"
has semgrep && run "multi-language SAST (semgrep)" semgrep scan --config auto --error --quiet || skip "semgrep missing"
log "== GATE 5: RUNTIME STRESS =="
if has python3; then
run "50 concurrent workers" python3 -c "
import concurrent.futures as c
with c.ThreadPoolExecutor(32) as e:
r=list(e.map(lambda i:i*i, range(50)))
assert len(r)==50"
fi
log "== GATE 6: EVIDENCE SEAL =="
log "pass=$PASS fail=$FAIL skip=$SKIP utc=$(date -u +%FT%TZ)"
sha256sum "$REPORT" | tee "$REPORT.sha256"
[ "$FAIL" -eq 0 ] && log "RESULT: ALL EXECUTED GATES PASSED" || log "RESULT: RELEASE BLOCKED"
exit $(( FAIL > 0 ))
5. Language-by-language commands
| Language | Syntax / types | Tests | Security |
|---|---|---|---|
| Python | python3 -m compileall -q . | pytest -q --cov | bandit -r . -ll, pip-audit |
| TypeScript / React | npx tsc --noEmit | npm test, Playwright | eslint ., npm audit |
| Java | mvn -q compile | mvn verify | SpotBugs, OWASP Dependency-Check |
| Go | go vet ./... | go test -race ./... | gosec ./..., govulncheck |
| C / C++ | gcc -std=c99 -Wall -Wextra -Werror -c | Unity or CMocka, run with -fsanitize=address,undefined | cppcheck, clang-tidy, Valgrind |
| Rust | cargo check | cargo test | cargo audit, cargo clippy -- -D warnings |
| HTML | npx html-validate "**/*.html" | Lighthouse CI | CSP header review, accessibility checks |
Protocol check for MCP and agent servers
Agent tool servers must answer JSON-RPC 2.0 correctly. Use the MCP Inspector for interactive checks, then script a smoke test so it runs on every commit:
npx @modelcontextprotocol/inspector
# smoke test: server must return a valid JSON-RPC 2.0 envelope
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | node dist/server.js | grep -q '"jsonrpc":"2.0"'
6. Deep dive: audit settings that matter in each language
The master script runs sensible defaults. For a release you will trust, tighten each language's own configuration. These are the settings that most often separate a passing demo from a production-ready build.
Python agents and MCP servers
Python services that expose tools to an LLM accept untrusted input by design, so validation and dependency hygiene matter more than style. Add type checking, a coverage floor and a severity threshold so the gate is measurable:
python3 -m mypy --strict src/
pytest -q --cov=src --cov-fail-under=80
bandit -r src -ll # medium and high severity only
pip-audit --strict # fail on any known vulnerable package
Treat any use of eval, exec, subprocess with shell=True, or unsafe deserialization in a tool handler as a blocker, not a warning.
TypeScript and React dashboards
Turn on "strict": true in tsconfig.json; without it, the type check proves very little. Pair ESLint with a security plugin, run component tests, and add one end-to-end test for the main operator workflow:
npx tsc --noEmit
npx eslint . --max-warnings 0
npm test -- --coverage
npx playwright test
npm audit --audit-level=high
Also confirm that the deployed page sends a Content Security Policy header and that no component uses dangerouslySetInnerHTML with unsanitized data.
Java backend pipelines
Java builds should fail on compiler warnings, static analysis findings and vulnerable dependencies. Run the full Maven lifecycle so tests, SpotBugs and dependency scanning execute together, and write at least one concurrency test that hammers shared state from many threads:
mvn -q verify
mvn -q spotbugs:check
mvn -q org.owasp:dependency-check-maven:check
Go services
Go gives you a built-in race detector, which is the cheapest concurrency audit available. Run it on every commit, and add fuzzing to any parser that reads external data:
go vet ./...
go test -race -count=1 ./...
govulncheck ./...
go test -fuzz=Fuzz -fuzztime=30s ./parser
C99 and Rust embedded firmware
Firmware has the least forgiving failure modes, so compile with every warning as an error and execute the logic on a host machine under sanitizers before it ever reaches hardware:
gcc -std=c99 -Wall -Wextra -Wpedantic -Werror -fsanitize=address,undefined -g -o fw_test tests/*.c src/*.c
./fw_test
valgrind --leak-check=full --error-exitcode=1 ./fw_test
cargo clippy -- -D warnings && cargo audit
For hard real-time loops, add a rule that bans malloc after initialization, and let a simple grep in your script enforce it.
HTML and web assets
Validate markup, check accessibility, and measure performance with the same tools your users' browsers expect: an HTML validator, Lighthouse in CI, and a review of response headers (CSP, X-Content-Type-Options, Referrer-Policy).
7. Sample audit report: what a real run looks like
This is genuine output from running the script on a tiny demo project (one Python file, one C file and one deliberately invalid HTML file) on a machine where most scanners were not installed. It shows the three outcomes you will see in practice: pass, skip and fail.
== GATE 1: INVENTORY ==
py=1 ts=0 java=0 go=0 c=1 html=1
== GATE 2-4: BUILD, TEST, SECURITY (per language) ==
[PASS] python compile
[SKIP] bandit missing
[SKIP] pytest missing
[SKIP] cppcheck missing
[FAIL] html validation
[SKIP] gitleaks missing
[SKIP] semgrep missing
== GATE 5: RUNTIME STRESS ==
[PASS] 50 concurrent workers
== GATE 6: EVIDENCE SEAL ==
pass=2 fail=1 skip=6
RESULT: RELEASE BLOCKED
Read it this way: one real failure blocks the release, and six skipped checks are a coverage gap, not a success. A report with many skips should be treated as incomplete. Install the missing scanners, or record a written reason why each one does not apply.
8. How to decide pass or fail
An audit without thresholds is just a log. Agree on the rules before the final run, and write them in your repository:
- Blockers: any failing build, test or type check; any high-severity SAST finding; any secret in the repository; any high or critical dependency advisory with a fix available.
- Must be explained: medium findings, skipped scanners and accepted false positives. Each needs a short written justification in the report or in a code comment such as
# nosec: reason. - Tracked, not blocking: low-severity findings, style warnings and coverage trends.
9. Troubleshooting common audit script problems
| Symptom | Likely cause | Fix |
|---|---|---|
$'\r': command not found | Windows line endings (CRLF) in the script | sed -i 's/\r$//' master_polyglot_audit.sh or set git config core.autocrlf input |
python: command not found | Git Bash exposes python3 or the Windows launcher py instead | Install Python and tick "Add to PATH", or alias python3 in the script |
Permission denied | Script is not executable | Run bash master_polyglot_audit.sh or chmod +x it |
npx hangs or asks to install | Tool not installed locally; interactive prompt in CI | Install as a dev dependency, or pass --yes deliberately |
| Scan is very slow | Scanning node_modules, build folders or virtual environments | Exclude them, and on pull requests scan only changed files |
| False positive blocks the build | Scanner cannot see your validation logic | Suppress that single line with a justification, never disable the rule globally |
| Passes locally, fails in CI | Different tool versions or missing environment variables | Pin tool versions and run the script inside the same container locally |
10. A practical maturity path for solo builders and small teams
You do not need every tool on day one. Teams finishing AI-assisted projects usually succeed by climbing in steps, which also answers the stalled-project problem described in why vibe coding projects stall:
- Level 1, build health: compile, type check and run the tests you already have.
- Level 2, basic security: add dependency audit and secret scanning. These two catch the most common real-world incidents.
- Level 3, static analysis: add SAST with Semgrep plus one language-specific scanner.
- Level 4, runtime assurance: add race detection, sanitizers, fuzzing and load tests.
- Level 5, continuous evidence: run everything in CI and archive checksummed reports for every release.
11. Key terms in plain language
- SAST (static application security testing): analyzing source code for vulnerabilities without running it.
- DAST (dynamic application security testing): probing a running application from the outside.
- SCA (software composition analysis): checking third-party packages for known vulnerabilities.
- Fuzzing: feeding random or malformed input to find crashes and parsing bugs.
- Race condition: a bug where results depend on the timing of threads or processes.
- JSON-RPC 2.0: the message format used by Model Context Protocol servers to receive requests and return results or errors.
- Evidence report: a timestamped record of what was checked and what happened, with a checksum so changes are detectable.
12. Most advanced audit and testing tools
These external tools complement the script. Links are marked nofollow because they point to third-party sites.
| Purpose | Tool |
|---|---|
| Multi-language SAST | Semgrep, SonarQube |
| Python security | Bandit |
| JS / TS quality | ESLint |
| Go security | gosec |
| Java bugs | SpotBugs |
| C / C++ analysis | Cppcheck, Valgrind |
| Rust dependencies | cargo-audit (RustSec) |
| Container and IaC scan | Trivy |
| Secret detection | Gitleaks |
| Load testing | k6, Artillery |
| MCP protocol inspection | MCP Inspector |
| Web quality | Lighthouse |
13. Wiring the script into CI
# .github/workflows/audit.yml
name: polyglot-audit
on: [push, pull_request]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: bash master_polyglot_audit.sh
- uses: actions/upload-artifact@v4
if: always()
with: { name: audit-evidence, path: "audit-report-*" }
14. Mapping audit gates to industry standards
A polyglot code audit is judged by the controls it supports. Auditors rarely ask which tool you used; they ask which control it supports. For a system like SmartTransit AI the gates map roughly as follows:
| Standard or framework | What it expects | Gate that produces evidence |
|---|---|---|
| OWASP ASVS / Top 10 | Input validation, dependency hygiene, no secrets in code | Gates 3 and 4 (tests, SAST, secret and dependency scans) |
| ISO/SAE 21434 (vehicle cybersecurity) | Verified security requirements for connected vehicle components | Gates 2 to 5 on the C/Rust edge layer |
| GDPR and regional data-protection law | Data minimization, traceable processing | Gate 6 evidence plus data-flow review of pipeline code |
| SOC 2 style change control | Repeatable, logged release checks | CI run history plus checksummed reports |
These mappings are a starting point, not certification. A script produces evidence; a qualified assessor decides whether it satisfies a standard.
SmartTransit AI release checklist
- Firmware builds with
-Wall -Wextra -Werrorand passes AddressSanitizer runs on the host simulator. - Every MCP tool rejects malformed arguments and returns a valid JSON-RPC 2.0 error, never a stack trace.
- Pipeline services pass the Go race detector or Java concurrency tests under load.
- Dashboard builds with zero type errors and a strict Content Security Policy.
- No secrets in git history, no high-severity dependency advisories, and the evidence report is attached to the release.
15. Common mistakes
- Hard-coded success messages. Always derive status from exit codes.
- Using
|| trueeverywhere. It hides real failures; use it only for optional tools, and log them as skipped. - Unscoped
findexpressions. Group patterns with\( -name '*.ts' -o -name '*.tsx' \)so exclusions apply to all of them. - Auditing AI-generated code by eye. Machine-written code needs the same gates as human code. See vibe coding limits: AI model or developer experience.
16. Frequently asked questions
How do I test code written in several languages from one command?
Use a bash script that detects each language by file extension, runs that language's native compiler, test runner and security scanner, records exit codes, and fails if any gate fails.
Can Git Bash run these audits on Windows?
Yes. Git Bash supports the commands used here. Tools such as Python, Node.js, Go and Java must be installed and on your PATH.
What is the difference between testing and auditing?
Testing checks behavior against requirements. Auditing checks security, compliance and process evidence, and records it so others can verify.
How do I audit a project that uses Python, TypeScript and Java together?
Run each language's own compiler, tests and scanner from one bash script, then add multi-language scanners such as Semgrep and a secret scan, and save the combined results as one checksummed report.
Is one SAST tool enough?
No. Use a language-specific scanner (such as Bandit or gosec) plus a multi-language scanner (such as Semgrep), then add dependency and secret scanning.
17. Conclusion: finish the loop with evidence
A polyglot code audit is not a single tool or a one-time event. It is a repeatable set of gates that every language in your system must pass before release, with results recorded so anyone can verify them later. Start with the master script, tighten each language's configuration, agree on pass and fail thresholds, and move the whole pipeline into CI. Whether you are shipping an AI agent, an MCP server, embedded firmware or a dashboard, the same discipline applies: build it, test it, scan it, stress it, and keep the proof. Teams that do this ship with fewer surprises and can answer a customer's or auditor's security questions in minutes instead of weeks.
18. Related resources
- Chip-agnostic smart transit AI architecture
- Vibe coding tools accuracy guide
- Vibe coding limits: AI model or developer experience
- Why vibe coding projects stall and how to finish them
- SEOSiri Developer Portal
- SEOSiri Open-Source on GitHub
Built something and not sure it is ready to ship?
Whether it is an AI agent, an MCP server, an IoT platform or a full-stack app, our engineering team can set up this audit pipeline for your repository, harden the failing gates, and hand you a verifiable evidence report.
👉 Request a technical audit consultation or explore our open tooling at the Developer Portal.