ESLEngineering Software Lab
ESL — Engineering Software Lab
AI-Assisted Software Engineering · Case Study

Ampcode × Terratest

Cloning, hardening, optimizing, testing & documenting a real public Terraform testing library — with rigorous, hallucination-free verification of every change.

Prepared by

ESL — Engineering Software Lab

Software Engineering Consultants

eswlab.com/contact-us →
Daniel Liezrowice
Author

Daniel Liezrowice

LinkedIn →
What's inside

Table of contents

Twenty-four slides across six chapters — from the initial ChatGPT brief through security hardening, a real bug fix, measured performance gains, rigorous verification, and the two upstream PRs. Tap any line to jump to that slide.

How it started

A question to ChatGPT

“I need a public Terraform demo project that will be used to show the capabilities of Ampcode to improve the performance of a Terraform project and test the improved code — with rigorous testing to make sure the conversion was done right: no bugs, no AI hallucinations.”

🌐 Public repository
🏗️ Real Terraform relevance
⚡ Refactor & performance
🧪 Regression & verification
🔒 Security hardening
🚫 Zero hallucinations
ChatGPT · thought for 11s

Recommendation: Gruntwork Terratest

Why it fits the demo

  • Purpose-built for automated infrastructure testing
  • First-class Terraform support & examples
  • Covers AWS, GCP, Azure, Docker & Kubernetes
  • Large, real-world Go codebase — ideal for refactor + regression testing
Source
github.com/gruntwork-io/terratest → terratest.gruntwork.io (docs) →

Apache-2.0 · maintained by Gruntwork.io

The target · size & complexity

A large, mature Go library

Terratest is a library imported by your _test.go files: it deploys real infrastructure, asserts against it, then tears it down. Scale measured from the clone:

443
Go source files
59,188
Lines of Go
22
Modules
244
Test files

Go 1.26

Required toolchain (auto-upgraded during the work).

Apache 2.0

Permissive OSS license · maintained by Gruntwork.

v1.x — maintenance

The v1 line receives security fixes only; v2 is in development. This shaped our PR choices.

Architecture

22 focused modules under modules/

IaC & container tooling

terraformterragruntpacker dockerhelmk8sopa

Cloud providers

awsazuregcp

Connectivity & execution

sshhttphelperdnshelper databaseshell

Utilities

randomretryfiles loggertestingteststructure

Supporting trees: examples/ (sample infra) · test/ (integration) · cmd/ (CLI) · internal/

The Ampcode mission

One prompt, seven mandates

  • Clone the Terratest repository
  • Explain the project & architecture
  • Security review using the Claude Mythos skill
  • Improve performance of the code
  • Optimize the code (surgical, minimal)
  • Perform every possible test to verify the solution
  • Document with a table, scores & explanations
  • Follow-up  Find the 2 most important issues → open PRs

Guardrail: every claim must be backed by a reproducible command — no unverified assertions, no hallucinated fixes.

End-to-end workflow

What Amp actually did

1

Clone

Shallow clone of Terratest

2

Explain

443 files · 22 modules mapped

3

Scan

Grype + Trivy · Claude Mythos

4

Optimize

Regexp hoisting · global rand

5

Fix bug

UniqueID collisions

6

Verify

build · vet · test · bench · re-scan

7

Document

Report + scorecard

8

2 PRs

Submitted upstream

Security assessment · method

Claude Mythos, evidence-based

Tooling

  • Grype — dependency & vuln database scan
  • Trivy — filesystem vuln + secret scan
  • Static pattern review across modules/
  • Authoritative sources: NVD, GHSA, Go vuln DB

Principles

  • Local, safe & non-destructive validation
  • Confidence rated: confirmed / plausible / theoretical
  • No inflated severity, no fabricated findings
  • Separate accepted design from real remediations
Findings

23 known CVEs in Go dependencies

Severity distribution (Trivy, go.mod) — with 3 rated CRITICAL by Grype among the x/crypto set.

High
14
Medium
7
Low
1
Unknown
1

Also flagged: actions/download-artifact@v4 (CI supply chain, High) and docs-site Ruby gems (out of product scope).

The headline risk

The golang.org/x/crypto SSH story

CRITICAL

14 x/crypto/ssh advisories

  • Denial of service (multiple vectors)
  • Authorization / authentication bypass
  • Unauthorized command execution

Why it matters here

Terratest's modules/ssh imports x/crypto/ssh directly — this isn't a dormant transitive dependency, it's on the library's real attack surface.

v0.49.0 — vulnerablev0.52.0 — fixed
Remediation

Dependencies bumped · re-scan clean

DependencyFromToResolves
golang.org/x/crypto0.49.00.52.014 SSH CVEs (Critical/High)
golang.org/x/net0.52.00.55.0HTML/HTTP2 XSS & DoS
jackc/pgx/v55.9.05.9.2SQL injection (database)
ulikunitz/xz0.5.100.5.15Memory-leak DoS
golang.org/x/sys0.42.00.45.0Overflow + required by x/crypto
23
CVEs before
go get + go mod tidy
0
CVEs after (Trivy & Grype)
Code-level review

Posture: already strong

✓ Positives

  • No InsecureSkipVerify (TLS)
  • No InsecureIgnoreHostKey
  • No weak crypto (md5/sha1/des/rc4)

◐ Accepted by design

  • SSH NoOpHostKeyCallback — ephemeral test hosts
  • math/rand for resource names (non-security)

✓ CI hardening

  • download-artifact@v4@v4.1.3
  • (kept out of PRs — see later)
Found by testing · a real bug

UniqueID() could return duplicates

Discovered when TestUniqueID failed — not caused by our edits.

Root cause

fast / parallel calls new PRNG seeded with time.Now().UnixNano() every call same tick → same seed identical “unique” IDs

Coarse Windows timer resolution makes the collision reliable; finer Linux CI timers hid it.

The fix

Use Go 1.20+ auto-seeded, concurrency-safe global math/rand no collisions verified 5/5 repeats · also 106× faster
Performance · what & how

Speedups per optimization

Technique: hoist constant regexp.MustCompile out of per-call scope into package-level vars (compile once); replace per-call PRNG allocation with the global source. Log scale ↓

ExtractArtifactIDpacker · regexp
4.8×
GetIndentlogger/parser · regexp
7.8×
TrimPackerVersionpacker · regexp
24.6×
UniqueIDrandom · global rand
106×
Axis (log): · 10× · 100×+ Docker project-name regexp → compile-once
Performance · latency

Nanoseconds per operation

before afterlower is better · scaled to max (9,025 ns)
GetIndent
before
921.5
after
118.3
ExtractArtifactID
before
5,610
after
1,172
TrimPackerVersion
before
4,581
after
185.9
UniqueID
before
9,025
after
85.1
Performance · memory

Allocations per operation

before afterlower is better · scaled to max (42)
GetIndent
before
17
after
0
0 allocs 🎉
ExtractArtifactID
before
42
after
1
TrimPackerVersion
before
42
after
1
UniqueID (bytes)
before
5,448 B
3
after
72 B · 2
Verification · the core of the demo

Every change was proven

  • go build ./...PASS full dependency tree
  • go vet ./...PASS whole library
  • Changed-package unit tests — PASS
  • go test -bench — before/after measured
  • CVE re-scan (Trivy + Grype) — 0
  • Bug repro fixed — 5/5 repeats
  • go mod tidy stable — CI check green
  • Surgical diff verified via git diff

Honest reporting

Pre-existing Windows-only test failures (needing Unix cat / diff) were identified and clearly labelled as not caused by our changes — no green-washing.

No AI hallucinations

Claim → Evidence matrix

ClaimReproducible evidence
“CVEs are fixed”trivy fs go.mod → 0 · grype dir:. → 0
“It's faster”go test -bench -benchmem (before vs after)
“The bug is fixed”go test -count=5 -run TestUniqueID → PASS
“Nothing broke”go build ./... & go vet ./... → PASS
“Changes are minimal”git diff — 7 files, isolated per PR

If it couldn't be shown with a command, it wasn't claimed.

Assessment scorecard

Before After

before afterscore out of 10
Dependency security
4
9
Correctness / reliability
5
9
Performance (hot paths)
6
9
Verifiability
7
9
6.0
Overall before
hardened & optimized
8.8
Overall after
Respecting maintainers

Why only two PRs

✓ Selected

  • The UniqueID bug fix — a real, non-obvious defect that no scanner detects
  • The dependency CVE bumps — high impact, and the repo has no Dependabot, so it's genuinely needed & on-policy for the security-only v1 line

✕ Deliberately left out

  • Regexp micro-optimizations — lower impact; likely out-of-scope for a security-only line
  • CI action pin — minor supply-chain nicety

Quality > quantity — don't flood the maintainers.

Contributions submitted upstream

Two focused pull requests

OPENMERGEABLE

PR #1860

fix(random): prevent UniqueID collisions from per-call time seeding

Correctness bug fix · isolated to modules/random.

github.com/gruntwork-io/terratest/pull/1860 →
OPENMERGEABLE

PR #1861

fix(deps): bump dependencies to resolve known CVEs

Security · go.mod/go.sum only · go mod tidy-clean.

github.com/gruntwork-io/terratest/pull/1861 →

Submitted from fork zuwasi/terratest against gruntwork-io/terratest:main. A CLA signature may be required before merge.

Deliverables & references

Cloned · hardened · optimized · tested · documented

Artifacts

  • Full assessment report — AMP_ASSESSMENT_REPORT.md
  • Working tree — C:\projects\terratest-BMC
  • Two upstream pull requests (#1860, #1861)
  • This presentation
ESL — Engineering Software Lab

Thank you

AI-assisted engineering, done responsibly: measured, verified, and contributed back — with zero hallucinations.

Daniel Liezrowice
Prepared by

Daniel Liezrowice · ESL

LinkedIn  ·  eswlab.com/contact-us
1 / 24
← Swipe to navigate →