Cybersecurity testing for complex and embedded systems
Midair turns what a code analysis suspects into tests that try to prove it. It runs those tests on your system and keeps the evidence of each run.
Start with one avenue into your product that worries you, such as the firmware update path. A pilot runs the loop on it with your suite and your device.
what to provean image with a bad signature is never installed analysis template fw-main, suspicious places: security test suite update-ts, branch per round delta device gw-lab-2 stage judge, iteration 2 of 5 found 1 demonstrated, 1 suspected trying H3: rollback to an older image
What cybersecurity testing is.And why one tool is not enough.
Cybersecurity testing checks how a system behaves when someone tries to misuse it. It looks for weaknesses an attacker could use: unsafe memory use, exposed services, weak builds and unchecked input.
One tool rarely settles the question. A code analysis says that a copy may overflow. A test shows whether a long input reaches it. The device shows how the binary was built and what else runs next to it.
Midair keeps the three views in one project. You name what worries you. Midair analyses the code, writes and runs tests, and reports what each run demonstrated.
The attack vector loop.Five stages, repeated until nothing new turns up.
An attack vector is one avenue into the system, together with a loop that keeps probing it. Pick a stage to see what happens there.
01 Analyse
- Who does it
- Midair and Visao
- What happens
- Midair forks a run from your analysis template with suspicious places turned on. Findings say what is wrong. Suspicious places say where the code decides something that nobody has read yet.
analysis run 318 · suspicious places: securitySUSPICIOUS security high authorization-decision verify.c:88 SUSPICIOUS security med crypto-primitive verify.c:41 finding std/mem/overflow unpack.c:142:9 Copy larger than the destination buffer 2 suspicious places, 1 finding go to the plan
02 Plan
- Who does it
- Your AI provider
- What happens
- The suspicious places, the findings and all that earlier rounds learned go to the AI provider. It returns the hypotheses to attack, a spec for the test suite and a norm for the Delta agent.
plan · iteration 2H1 verify.c:88 accepts an image when the
signature check returns an error
H2 unpack.c:142 overflows on a long file name
H3 an older signed image can be installed again
spec tests for H1-H3 in group update_path
norm forbid: module, memexec ports: 22/tcp03 Write tests
- Who does it
- Claude Code or Codex CLI
- What happens
- The spec goes to Claude Code or the Codex CLI. The tool updates your test suite repository and pushes a branch. The suite's own spec prompt stays as it is.
generator · Claude Code · update-tscloned update-ts
added update_path/bad_signature.c
added update_path/long_name.c
added update_path/rollback.c
pushed av/update-path/iter-204 Run
- Who does it
- Test Environment and Delta
- What happens
- Midair forks a run from your test template, pinned to the new branch. When a device is attached, Delta watches it while the suite runs.
run 1207 · branch av/update-path/iter-2update_path/bad_signature FAILED H1: image installed
update_path/long_name PASSED H2: name rejected
update_path/rollback SKIPPED H3: no older image
delta gw-lab-2 cycle 4411 to 4415
+ port:4444/tcp/LISTEN05 Judge
- Who does it
- Your AI provider
- What happens
- The verdicts and the drift that Delta saw go back to the provider. It answers which hypotheses the run settled, which it could not reach, and whether another round would learn anything new.
judge · iteration 2demonstrated H1 run 1207, bad_signature not shown H2 long names rejected suspected port 4444 opened during the run not reached H3 needs two signed images another round: yes, for H3
What the loop never does.And when it stops.
It does not change the code under test.
The loop edits the test suite only. A loop that could edit the code could also make its own tests pass.
It does not decide what is a vulnerability.
Each finding carries its evidence and a mark: demonstrated by a run, or only suspected. Demonstrated findings come first. A person confirms them.
It stops on its own.
The loop ends at the iteration limit you set, or earlier when another round would learn nothing new. Stop ends it at once, and the runs it started still finish with real results.
It keeps going without your browser.
The loop advances on the server. Closing the page does not stop it, and a server restart resumes it. A stage that does not move for six hours ends the loop with a message.
One defect, three layers.Each layer sees a different part.
Our demonstration suite plants defects on purpose and checks that the scanners find them. This example joins two of them in one small program: a strcpy into an 8-byte buffer, and a build without a stack protector or PIE.
1#include <string.h>2#include <stdio.h>3char buffer[8];4void copy_name(const char *name)5{6 strcpy(buffer, name);7}8int main(int argc, char **argv)9{10 if (argc > 1)11 copy_name(argv[1]);12 printf("%s\n", buffer);13}$cc -O0 -fno-builtin -fno-stack-protector \ -fno-PIE -no-pie unsafe.c -o unsafe#installed on the device as /opt/demo/unsafe
The source shows the copy.
- What it sees
- copy_name() copies a string of any length into an 8-byte buffer.
- What it cannot see alone
- How the binary was built, and whether a long input ever reaches this line.
visao · unsafe.c · Exampleunsafe.c:6:5 error std/mem/overflow Copy larger than the destination buffer 1 finding
The test shows the build.
- What it sees
- The release binary still calls strcpy from copy_name. It has no stack canary and is not position-independent (PIE).
- What it cannot see alone
- What else is installed and listening on the device next to it.
run 1211 · tsf-cybersec · Examplebinscan unsafe NX yes PIE no canary no
objdump banned call: strcpy in copy_name
release/hardening FAILED binary.no-canary
binary.not-pie
release/banned_calls FAILED binary.banned-callThe device shows what shipped.
- What it sees
- The installed binary breaks the hardening policy because it lacks a stack canary. Delta records its checksum, so a later rebuild shows up as drift.
- What it cannot see alone
- The source line. Midair shows the device result next to the code finding, in one problem list.
delta --binaries /opt/demo --cfg policy.json · Examplehardening Binary '/opt/demo/unsafe' lacks required mitigation: stack canary file /opt/demo/unsafe csum 3f9a…e10c exit code 1
Questions.Short answers.
What is cybersecurity testing?
Cybersecurity testing checks how a system behaves when someone tries to misuse it. It combines code analysis, targeted tests and checks on the running device to find weaknesses that an attacker could use.
What is an attack vector in Midair?
An attack vector is one avenue into your system that you want probed, such as the firmware update path. Midair runs a loop on it: analyse, plan, write tests, run and judge. The loop repeats until a round learns nothing new or reaches your iteration limit.
Does Midair decide what counts as a vulnerability?
No. Midair marks each finding as demonstrated by a run or only suspected, and keeps the evidence next to it. A person confirms it.
Does the loop change our source code?
No. The code generator edits only the test suite repository and pushes a branch. The code under test stays as it is.
What do the generated tests look like?
They are Test Environment tests in C that use the tsf-cybersec library. It checks how binaries were built, what a host listens on, what it connects to, and captured traffic. Each verdict names the hypothesis it settles.
What do we need for a pilot?
One avenue that worries you, the source code, a test suite repository and, if you have one, a device on a bench. The pilot sets up the first attack vector with you.
Start with one avenue.The one that worries you most.
Name what you want proved. A pilot runs the loop on your code, your suite and your device, and shows what each round demonstrated.
Join the waitlist