DevSecOps — Fundamentals
7 questions — read through for prep, or practice this course interactively.
What does "shift-left" actually mean in DevSecOps, and where's the highest-leverage place to start if a team has none of it today?Technical
How to answer
Define shift-left precisely — it's about when in the lifecycle a security check runs, not a vague "security is everyone's job" slogan — then take a real position on where to start. Interviewers are checking whether you'd boil the ocean (rolling out every scanner at once) or pick the cheapest, highest- signal win first.
Example answer
Shift-left means moving security checks earlier in the software lifecycle — into the IDE and the pull request — instead of running them only right before a release, or worse, finding out from an external report after something's already in production. The reasoning is a cost curve: a bug caught while someone's writing the code costs minutes to fix; the same bug caught in a security audit after it's merged costs a ticket, a context-switch, and a re-review; caught in production it can mean an incident, customer notification, and possibly a compliance finding. If a team has nothing today, I wouldn't start by rolling out a full SAST/DAST suite — I'd start with secret scanning and dependency (SCA) scanning as a required PR check. Both are cheap to run, have very low false-positive rates compared to SAST, and catch two of the most common real-world breach vectors — a leaked credential or a known-vulnerable dependency — without asking developers to interpret ambiguous static-analysis findings on day one. SAST and DAST come next, once the team has a working pattern for triaging findings instead of just ignoring a noisy new gate.
What interviewers listen for
a precise definition, not a slogan; a concrete, sequenced rollout plan rather than "just shift everything left at once"; reasoning about false-positive rate and blast radius when picking what to start with, not just picking a familiar tool.
What's your experience integrating security scanning — SAST, DAST, or SCA — into a CI/CD pipeline?Experience
How to answer
Walk through a real pipeline you've built or maintained rather than reciting tool definitions. The strongest answers talk about the operational problem almost everyone hits — noisy findings — and how you actually solved it, not just which tool you ran. (This is inherently personal — the answer below is one adaptable example, not the one correct shape.)
Example answer
"On my last team we ran Semgrep on every pull request using a pre-built ruleset plus a
few custom rules we'd written for patterns we'd been burned by before, like hardcoded credentials matching
our own key format. For dependencies, we ran npm audit/pip-audit in CI and had Dependabot open PRs for
anything patchable automatically. The real problem wasn't picking tools, it was noise: the first time we
turned on SAST as a hard CI gate, it failed on hundreds of pre-existing findings in code nobody was touching,
and the team's reaction was to just add a blanket ignore rule, which defeats the point. We fixed that with a
baseline-and-ratchet approach — we recorded the existing findings as an accepted baseline, gated only on
new findings introduced by a PR's diff, and set a quarterly goal to burn down a slice of the baseline. DAST
we ran less often — a ZAP baseline scan against staging on every deploy, and a full active scan only on a
schedule, never against production, since active scanning genuinely attacks the running app. That staged
approach — SCA and secrets on every PR, SAST gated on new findings only, DAST against staging on a slower
cadence — is what actually got adopted instead of resented."
What interviewers listen for
specific tools and how they were wired into CI, not just named; the noise/ false-positive problem named explicitly, with a real fix (baseline-and-ratchet, not "we just fixed the findings"); correct understanding that DAST attacks a running app and should never target production directly.
Scenario
A developer just messaged you: ten minutes ago they accidentally committed and pushed a live AWS access key to a shared GitHub repository. The repo is private, but a dozen people have access, and it's already been fetched by at least one CI job.
Walk me through exactly what you do in the next thirty minutes.Scenario
How to answer
Show the correct priority order — the key is already possibly compromised the moment it
left the laptop, so response starts with treating it as compromised, not with trying to erase it from
history first. Candidates who lead with git filter-branch/BFG as step one are missing that removing it
from git history does nothing about the fact that it already left the repo in cleartext and may already be
cached, forked, or scraped.
Approach
Rotate the credential first — revoke the leaked key and issue a new one — because that is the
only step that actually closes the exposure; everything else is cleanup that happens after the bleeding is
stopped. Check CloudTrail (or the equivalent access log) for any usage of the key between the commit time
and the rotation, since a key can be scraped and used within minutes by automated credential-harvesting bots
that scan public and even some private/forked repositories. Only after rotation and the usage check, clean
the git history (git filter-repo or BFG, then a force-push and a heads-up to anyone with a local clone,
since rewritten history breaks their existing branches). Finally, treat it as a process gap, not just an
incident: this is exactly the kind of leak a pre-commit secret-scanning hook (gitleaks) or a mandatory
PR-time scan would have caught before the push ever happened.
Example answer
"First move, before touching git history at all, is to revoke and rotate the key — in
IAM that's deactivating the old access key and issuing a new one, then updating whatever's using it. That's
the only action that actually stops the exposure; nothing else matters until that's done. While that's
happening, I'd check CloudTrail for any API calls made with that key since it was pushed, because secret-
scraping bots do actively scan for exposed credentials and can use one within minutes even in a private repo
if it was ever cached by a fork, a CI runner, or a third-party integration. Once the key is dead and I've
confirmed there's no suspicious usage, I'd clean the git history with git filter-repo, force-push, and
message everyone with a local clone that they need to re-clone or rebase, since a rewritten history breaks
their existing checkouts. Last, I'd treat the root cause as the real finding for the postmortem: we didn't
have a pre-commit secret scanner or a required PR-time gitleaks check, and that's what should have caught
this before it ever left the laptop."
What interviewers listen for
rotation/revocation named as the immediate first action, not history cleanup; explicit reasoning that a "private" repo doesn't mean the key wasn't already exposed to scraping; correct understanding that rewriting git history alone doesn't undo an already-leaked credential; ties the incident back to a preventive control (pre-commit or PR-gate scanning) rather than treating it as a one-off.
What's wrong with this Dockerfile, and how would you fix it before it ships to production?Code Review
FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
ENV DATABASE_PASSWORD=Sup3rSecret!
EXPOSE 3000
CMD ["node", "server.js"]How to answer
There are three independent, stacked problems here, not one — call out all of them, in order of actual production risk, rather than stopping at the first thing you notice.
Example answer
"Three real issues, and I'd fix all three, not just one. First, FROM node:latest is a
floating tag — the exact base image changes every time it's rebuilt, so you can't reproduce what's actually
running, and you have no fixed reference point to check for known CVEs against; it should be pinned to an
exact version, ideally by digest. Second, and the most serious: ENV DATABASE_PASSWORD=Sup3rSecret! bakes a
secret directly into the image layer history. Anyone who can pull the image — including via a registry
misconfiguration or a compromised CI cache — can run docker history or inspect the image's layers and read
that password in plaintext, even if a later instruction tries to overwrite or unset it; the layer with the
secret is still there. That value needs to come from a runtime secret injection mechanism — a mounted
secret, a Kubernetes Secret, Vault — never a build-time ENV. Third, there's no USER directive, so this
container runs as root by default; if the app is ever compromised, the attacker has root inside the
container, which is a much bigger blast radius than a non-root process would give them. I'd also flag that
this isn't a multi-stage build — the final image ships whatever devDependencies and build tooling npm install pulled in, which is more attack surface and a bigger image than a runtime-only stage needs."
What interviewers listen for
finds all three issues, not just the most obvious one; explains why the
baked-in secret is dangerous even if a later line looks like it removes it (layer history persists);
correctly identifies the missing non-root USER as a blast-radius issue, not just a style nitpick.
Your company just watched a widely-used open-source project get compromised through a poisoned build pipeline, similar in shape to the SolarWinds attack. Design supply-chain security controls for your own CI/CD pipeline so a comparable attack wouldn't succeed silently.System Design
Clarifying questions
What CI platform is this — GitHub Actions, GitLab, Jenkins — since the concrete hardening controls differ by platform? Are third-party actions/plugins currently pinned to anything, or pulled by a mutable tag? Does the deploy target consume container images, raw artifacts, or both? Is there any existing requirement (customer contract, government/regulated industry) to produce an SBOM or provenance attestation, or would this be purely internal hardening?
Approach
Harden the pipeline itself first: pin every third-party action/plugin to an exact, immutable
commit SHA rather than a mutable tag like v4 (a compromised or re-tagged upstream action is exactly the
SolarWinds-shaped attack — the build trusts whatever that tag currently points to); require signed commits
on protected branches; and default every workflow's token permissions to read-only, granting write scopes
only where a specific job genuinely needs them, closing off the "pwn request" pattern where a pull-request-
triggered workflow runs untrusted code with access to repo secrets. Then instrument the build to produce
evidence: generate an SBOM (via Syft or Trivy, in CycloneDX or SPDX format) for every build artifact, sign
the final artifact/image with Cosign using Sigstore's keyless signing (Fulcio issues a short-lived cert off
an OIDC identity, Rekor logs it in a public transparency log — no long-lived private key to protect or leak),
and attach an in-toto/SLSA provenance attestation proving which source commit, which pipeline, and which
inputs produced that specific artifact. Finally, gate the deploy step on verification — the deploy pipeline
checks the signature and provenance before pulling an image into production, and a continuous SBOM-
monitoring tool (Dependency-Track) re-checks every previously-generated SBOM against newly disclosed CVEs,
since a component clean at build time can become vulnerable weeks later.
Trade-offs
Keyless signing removes the operational risk of a long-lived signing key leaking, but it shifts trust onto the OIDC identity provider issuing the short-lived certificate — that trust boundary needs its own review, since anyone who can mint a token as the expected workflow identity can sign as it. Enforcing signature/provenance verification as a hard deploy gate from day one is safer but adds real friction and will break existing pipelines that were never producing this evidence; I'd roll it out in audit/report-only mode first, fix what it flags, and only then flip it to a hard gate. Full SLSA Build Level 3 — hermetic, isolated, non-interactive build platforms — is the strongest guarantee but is genuinely expensive to reach org-wide; a sequenced rollout (start at provenance-only, then signed builds on protected infrastructure, then full isolation) gets real security value sooner than waiting to do it all at once.
Example answer
"I'd start with the pipeline itself, since that's what actually got compromised in the SolarWinds-shaped attack: pin every third-party action to a commit SHA instead of a tag, and lock down workflow token permissions so a PR-triggered job can't quietly exfiltrate secrets — that closes the 'pwn request' pattern. On top of that, every build produces real evidence: an SBOM via Syft, a Cosign signature using keyless signing so there's no private key sitting in a secrets manager to leak, and an in-toto attestation tying the artifact back to the exact commit and pipeline that built it. The deploy step then verifies that signature and provenance before anything reaches production — so even if someone did manage to push a malicious build, it fails to pass verification instead of silently deploying. I'd roll the verification gate out in report-only mode first, since flipping it to a hard block on day one against pipelines that have never produced this evidence would just break everything at once."
What interviewers listen for
asks clarifying questions before designing, instead of reciting a memorized SBOM-and-signing checklist; names the "pwn request" / mutable-tag pattern as the actual mechanism behind a SolarWinds-shaped attack, not just "supply chain attacks are bad"; explains keyless signing's trust trade-off rather than presenting it as a free win; sequences the rollout (audit mode before hard gate) instead of proposing a big-bang cutover.
What's the difference between a SOC 2 Type I and a Type II report, and why would a security team push to get to Type II even though it's slower and more expensive?Technical
How to answer
Give the precise distinction — point-in-time design review vs. sustained operating effectiveness — then explain why that distinction actually matters to a customer evaluating the report, not just recite the definitions.
Example answer
A SOC 2 Type I report attests that your controls are designed correctly as of one specific date — an auditor reviews the control descriptions and confirms they'd work if operated as described, but doesn't verify they were actually followed. A Type II report covers a window, typically six to twelve months, and the auditor tests whether those controls were actually operating effectively the whole time — pulling evidence like actual access-review tickets, actual vulnerability-scan results, actual incident records, not just policy documents. The reason a security team pushes for Type II despite the extra cost and a much longer timeline is that a Type I report only proves you wrote a good policy, not that you followed it — a sophisticated enterprise customer's security team knows this and will often treat a Type I report as a starting point, not sufficient evidence on its own, before they'll sign a contract involving their data. Type II is what actually closes enterprise deals that have real security due-diligence review, because it's evidence of practice, not just design.
What interviewers listen for
correctly distinguishes "controls are designed well" from "controls were actually followed," not just "one is shorter than the other"; explains the practical business reason (sales/ procurement leverage) a team invests in Type II rather than treating it as pure compliance box-checking.
Tell me about a time engineering pushed back on a security requirement you were trying to introduce, and how you handled it.Behavioral
How to answer
Use STAR. The interviewer wants to see that you can drive a security change without resorting to a mandate that just gets quietly ignored or routed around — DevSecOps culture depends on buy-in, not just authority, and a story that ends with "I made them do it" is a weaker answer than one that ends with engineering actually wanting the change.
Situation
I was rolling out a hard CI gate that would block merges on any newly introduced critical SAST finding, after we'd had a near-miss where a SQL injection pattern nearly shipped. The lead of one of our larger teams pushed back hard, arguing it would slow down an already-tight release schedule and that the scanner threw too many false positives to trust.
Task
I needed the gate adopted without it turning into a rule people quietly disabled or routed around, which is exactly what had happened with a previous, less carefully rolled out security tool.
Action
Instead of insisting on the mandate as-is, I asked to sit with two of his engineers for an afternoon and go through the actual findings the scanner had produced on their codebase over the past month. About a third genuinely were false positives from a specific pattern our custom ruleset mis-flagged, so I fixed that rule instead of arguing it wasn't a real problem. I also proposed the gate only block new critical findings introduced by a given PR's diff, not the full pre-existing backlog, so the team wasn't suddenly blocked on unrelated legacy code. With the rule fixed and the scope narrowed to new findings only, I brought the same proposal back to the lead with actual before/after numbers instead of just a policy argument.
Result
The gate shipped two weeks later than my original timeline, but with the team's actual buy-in instead of a mandate they'd have found a way around — and the false-positive fix I made for their codebase turned out to reduce noise for two other teams using the same ruleset. Six months later that team hadn't disabled the gate once, which the team that had a security tool forced on them the year before had done within a month.
What interviewers listen for
the pushback is treated as a signal to investigate (some of it was a real tooling problem), not dismissed as engineering just resisting security; a concrete change in approach — not just "I explained why it mattered" — that actually addressed the objection; a result that shows durable adoption, not just that the policy technically shipped.