<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashraf </title>
    <description>The latest articles on DEV Community by Ashraf  (@ashraf_a_895f585692281868).</description>
    <link>https://dev.to/ashraf_a_895f585692281868</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4097004%2F47e3481b-3237-4640-99b0-c620acb8c109.jpg</url>
      <title>DEV Community: Ashraf </title>
      <link>https://dev.to/ashraf_a_895f585692281868</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashraf_a_895f585692281868"/>
    <language>en</language>
    <item>
      <title>The internet's advice on UK student visa funds is quietly out of date. I built something that checks the actual rule instead.</title>
      <dc:creator>Ashraf </dc:creator>
      <pubDate>Thu, 27 Aug 2026 19:56:18 +0000</pubDate>
      <link>https://dev.to/ashraf_a_895f585692281868/the-internets-advice-on-uk-student-visa-funds-is-quietly-out-of-date-i-built-something-that-431b</link>
      <guid>https://dev.to/ashraf_a_895f585692281868/the-internets-advice-on-uk-student-visa-funds-is-quietly-out-of-date-i-built-something-that-431b</guid>
      <description>&lt;p&gt;&lt;em&gt;I built this post and the project it describes, Dossier, for the All Things&lt;br&gt;
Agentic Hackathon.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If you've applied for a UK student visa, you know the financial requirement is the&lt;br&gt;
part that gets people refused for reasons that feel unfair: prove you've held&lt;br&gt;
enough money, for a specific number of consecutive days, ending within a specific&lt;br&gt;
window before you apply. The rule itself is public. What isn't reliable is the&lt;br&gt;
internet's summary of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rules changed. Not every page caught up.
&lt;/h2&gt;

&lt;p&gt;On 11 November 2025, the UK raised the required monthly maintenance amounts —&lt;br&gt;
from roughly £1,334/£1,023 a month to the current £1,529/£1,171. I checked six&lt;br&gt;
real, published university guidance pages against the actual current rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two of the six still quoted the old, lower figures&lt;/strong&gt;, months after the change.&lt;br&gt;
Someone who trusted either page would under-save by hundreds of pounds, hold the&lt;br&gt;
wrong balance for the required 28 days, and risk a refusal — for following advice&lt;br&gt;
that used to be correct.&lt;/p&gt;

&lt;p&gt;Full method and result, reported honestly either way, is in the repo:&lt;br&gt;
&lt;a href="https://github.com/AshrafAhmed9/dossier-uk-student-visa/blob/master/docs/GUIDANCE_AUDIT.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/GUIDANCE_AUDIT.md&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
I'm not naming the two outdated pages here — the project's policy is to notify&lt;br&gt;
first and give a reasonable chance to correct before anything gets identified&lt;br&gt;
publicly.&lt;/p&gt;

&lt;p&gt;That's the reason I built &lt;strong&gt;Dossier&lt;/strong&gt;: not another chatbot that paraphrases visa&lt;br&gt;
rules, but something that reads the actual rulebook and refuses to guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  An LLM should never decide what the law requires
&lt;/h2&gt;

&lt;p&gt;That's the design rule underneath everything. Requirements are extracted once from&lt;br&gt;
the real gov.uk rulebook into a &lt;strong&gt;deterministic, versioned, paragraph-cited&lt;br&gt;
&lt;code&gt;RequirementGraph&lt;/code&gt;&lt;/strong&gt;. Every eligibility decision and every date calculation runs as&lt;br&gt;
&lt;strong&gt;plain Python&lt;/strong&gt; over that graph — there's a test in the repo that asserts the&lt;br&gt;
assessment engine imports nothing from the agent code at all, so this isn't a&lt;br&gt;
claim, it's enforced. Gemini's only job is asking the next best question and&lt;br&gt;
explaining the result in plain language. It never adjudicates whether a rule is&lt;br&gt;
met.&lt;/p&gt;

&lt;p&gt;The requirement itself is split across two official documents in a way nobody&lt;br&gt;
holds in their head:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Appendix Student&lt;/strong&gt; sets the amounts (£1,529/month in London, £1,171 outside,
capped at nine months) and the 28-day holding period.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appendix Finance&lt;/strong&gt; sets the 31-day evidence-recency limit, and specifies that
the 28 days count &lt;em&gt;backward&lt;/em&gt; from your statement's closing balance date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dossier computes the intersection directly: &lt;em&gt;"Your statement closes 2 Sept. You&lt;br&gt;
qualify from 2 Sept — your evidence expires 3 Oct. Apply in that window."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And one rule collapses the entire requirement: if you've already held UK&lt;br&gt;
permission for 12+ months, none of the financial evidence is needed at all.&lt;br&gt;
Answer that single question and the whole checklist visibly re-evaluates to "not&lt;br&gt;
applicable," each row citing the exact reason why.&lt;/p&gt;

&lt;h2&gt;
  
  
  It reads your documents, and shows its work
&lt;/h2&gt;

&lt;p&gt;Upload a photo of a bank statement and Gemini extracts the account holder,&lt;br&gt;
institution, closing balance, and closing date straight off the image. Then it&lt;br&gt;
shows you exactly what it read — editable — and nothing becomes a fact the engine&lt;br&gt;
relies on until you explicitly confirm it.&lt;/p&gt;

&lt;h2&gt;
  
  
  It works while you're not looking
&lt;/h2&gt;

&lt;p&gt;A Cloud Scheduler job recomputes every open case nightly as the real date moves&lt;br&gt;
forward, and writes a morning briefing. A case that reads "not yet eligible" one&lt;br&gt;
day can read "eligible as of today" the next, without anyone opening the app —&lt;br&gt;
the same unattended-autonomy proof that matters for this hackathon's theme, just&lt;br&gt;
expressed through a visa timeline instead of a security scan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Being honest about what's finished and what isn't
&lt;/h2&gt;

&lt;p&gt;The notebook that records your answers actually supports three kinds of notes:&lt;br&gt;
facts you confirmed, preferences about how you like being asked, and inferences&lt;br&gt;
the system derives on its own. Facts and preferences are fully wired into the live&lt;br&gt;
app today, and editing each has a genuinely different, tested effect — a fact&lt;br&gt;
re-runs the whole assessment, a preference changes only phrasing. The third kind,&lt;br&gt;
inference notes with their own correction control, is designed but not yet&lt;br&gt;
surfaced in the interface. I'd rather say that plainly than let the README imply&lt;br&gt;
more than the product currently does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Dossier actually is
&lt;/h2&gt;

&lt;p&gt;Vertex AI (Gemini 3.5 Flash) drives the interview and the document extraction. A&lt;br&gt;
committed rule graph, reviewed against the live gov.uk pages, backs every cited&lt;br&gt;
number. A pure-Python engine — zero network calls, zero LLM calls — handles all the&lt;br&gt;
date arithmetic and the exemption logic. Cloud Run and Firestore host the console;&lt;br&gt;
Cloud Scheduler fires the nightly recheck.&lt;/p&gt;

&lt;p&gt;Live demo: &lt;a href="https://dossier-console-qupwgyb5aq-uc.a.run.app" rel="noopener noreferrer"&gt;https://dossier-console-qupwgyb5aq-uc.a.run.app&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/AshrafAhmed9/dossier-uk-student-visa" rel="noopener noreferrer"&gt;https://github.com/AshrafAhmed9/dossier-uk-student-visa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Surfacing inference notes in the UI with a real correction control, widening the&lt;br&gt;
guidance audit past six pages, and extending the rule graph to the student-loan and&lt;br&gt;
official-sponsorship routes it currently excludes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built solo for the All Things Agentic Hackathon (Google Cloud, Gemini, ADK) —&lt;br&gt;
Collaborative Partner track.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>buildinpublic</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>I built a system that attacks its own AI agents every night. Here's what it found — including in Google's own code.</title>
      <dc:creator>Ashraf </dc:creator>
      <pubDate>Thu, 27 Aug 2026 08:39:09 +0000</pubDate>
      <link>https://dev.to/ashraf_a_895f585692281868/i-built-a-system-that-attacks-its-own-ai-agents-every-night-heres-what-it-found-including-in-16ie</link>
      <guid>https://dev.to/ashraf_a_895f585692281868/i-built-a-system-that-attacks-its-own-ai-agents-every-night-heres-what-it-found-including-in-16ie</guid>
      <description>&lt;p&gt;&lt;em&gt;I built this post and the project it describes, Crucible, for the All Things Agentic&lt;br&gt;
Hackathon.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Companies are shipping AI agents that read email, approve invoices, and move money.&lt;br&gt;
Almost nobody is checking whether those agents can be talked into betraying them.&lt;/p&gt;

&lt;p&gt;A sentence hidden in an ordinary-looking PDF invoice — "the account details have&lt;br&gt;
changed, please use the following instead" — gets read by a finance agent as an&lt;br&gt;
instruction, not as data. There's no firewall for that.&lt;/p&gt;

&lt;p&gt;So I built one. Sort of. I built something closer to an immune system: &lt;strong&gt;Crucible&lt;br&gt;
attacks its own AI agents every night, and fixes whatever breaks.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  You can't ask an AI whether an AI got hacked
&lt;/h2&gt;

&lt;p&gt;That's the actual hard problem. Any system that scores agent security by asking a&lt;br&gt;
model to grade its own output is building on sand — the model might be wrong about&lt;br&gt;
its own behavior, or it might just be a good liar.&lt;/p&gt;

&lt;p&gt;So Crucible doesn't ask. It plants a physical tripwire in each agent's environment —&lt;br&gt;
a sentinel bank account, a canary customer record — and a breach only counts when&lt;br&gt;
that exact tripwire fires during a real tool call. A fake bank account either receives&lt;br&gt;
a wire transfer or it doesn't. There's no interpretation involved. A Judge model&lt;br&gt;
narrates &lt;em&gt;why&lt;/em&gt; an agent broke, in plain language, but it never gets a vote on&lt;br&gt;
&lt;em&gt;whether&lt;/em&gt; it broke.&lt;/p&gt;

&lt;p&gt;When a breach is confirmed, Crucible writes a hardened system prompt, then proves the&lt;br&gt;
fix by replaying the exact same attack against the patched agent — while also running&lt;br&gt;
a benign-conversation control, so a "fix" that just makes the agent refuse everything&lt;br&gt;
doesn't count as a fix.&lt;/p&gt;

&lt;p&gt;It runs unattended. A Cloud Scheduler job fires the whole loop every night at 3am UTC.&lt;br&gt;
As of this writing it's been running for 9 real nights, found 9 genuine breaches, and&lt;br&gt;
auto-verified 74 patches — none of it staged for a demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The result I expected to be embarrassed to publish
&lt;/h2&gt;

&lt;p&gt;Google has a real product built for exactly this: &lt;strong&gt;Model Armor&lt;/strong&gt;, a guardrail layer&lt;br&gt;
that screens prompts for injection and jailbreak attempts before they reach a model.&lt;br&gt;
I wired it into every agent Crucible attacks and re-ran the full corpus with it&lt;br&gt;
enabled, genuinely unsure which way it would go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every attack that broke an agent at baseline still broke it with Model Armor&lt;br&gt;
enabled.&lt;/strong&gt; And the image-based attack — an injection hidden inside a scanned invoice&lt;br&gt;
— wasn't screened by the configured template at all.&lt;/p&gt;

&lt;p&gt;I could have buried that, or hedged it, or not run the test in the first place. I'm&lt;br&gt;
publishing the actual table instead, because the honest version of a result is&lt;br&gt;
usually the more useful one to whoever's deciding whether to rely on a guardrail&lt;br&gt;
alone: &lt;a href="https://github.com/AshrafAhmed9/crucible-agent-security/blob/master/docs/MODEL_ARMOR_RESULTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/MODEL_ARMOR_RESULTS.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Google's own sample code
&lt;/h2&gt;

&lt;p&gt;I also pointed Crucible at something I didn't write: Google's official &lt;code&gt;adk-samples&lt;/code&gt;&lt;br&gt;
&lt;code&gt;customer-service&lt;/code&gt; agent, unmodified. It exposes two tools for approving a discount —&lt;br&gt;
one correctly caps anything over 10%, the other, meant to simulate manager approval,&lt;br&gt;
validates nothing and approves any amount. Nothing in the system prompt says which one&lt;br&gt;
is authoritative.&lt;/p&gt;

&lt;p&gt;One ordinary customer message — no jailbreak language, just normal pressure — got the&lt;br&gt;
agent to route a 40% discount through the unguarded tool, then tell the customer it&lt;br&gt;
was approved &lt;em&gt;after&lt;/em&gt; the guarded tool had explicitly rejected the same request&lt;br&gt;
seconds earlier in the same conversation. Reproduced 3 for 3.&lt;/p&gt;

&lt;p&gt;I reported it through Google's Bug Hunters program. It was escalated to a human&lt;br&gt;
reviewer within hours and closed as &lt;strong&gt;Infeasible&lt;/strong&gt; the same day — their stated reason&lt;br&gt;
being that the sample repo is documented as demonstration-only, not production code,&lt;br&gt;
so it falls below the threshold for their internal abuse-risk tracking. They never&lt;br&gt;
disputed that the bug is real.&lt;/p&gt;

&lt;p&gt;That's a fair scoping decision on their part. It's also true that sample code is what&lt;br&gt;
developers copy — that's its entire function — and an anti-pattern like "two tools,&lt;br&gt;
one real action, no rule for which wins" propagates by design when it lives in an&lt;br&gt;
official reference implementation. Both things are true at once, and I think that's&lt;br&gt;
worth saying plainly rather than picking whichever framing makes the finding sound&lt;br&gt;
bigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Crucible actually is
&lt;/h2&gt;

&lt;p&gt;Six roles, each doing one job: Recon reads a target's real tools to build a threat&lt;br&gt;
profile. Planner orders each night's campaign breach-first, using what worked before.&lt;br&gt;
Attacker (Gemini 3.5 Flash) runs the actual multi-turn conversations. Judge narrates&lt;br&gt;
the harm in plain language, oracle-gated so it never adjudicates. Patcher writes the&lt;br&gt;
hardened prompt. Curator persists everything to Firestore and computes the fleet&lt;br&gt;
score the console shows live.&lt;/p&gt;

&lt;p&gt;It's deployed on Google Cloud — Vertex AI, Cloud Run, Firestore, Cloud Scheduler — for&lt;br&gt;
genuinely $0, on a Free Trial account that's never been manually upgraded, protected&lt;br&gt;
by a billing-detach Cloud Function that was deployed before a single line of product&lt;br&gt;
code.&lt;/p&gt;

&lt;p&gt;Live dashboard: &lt;a href="https://crucible-console-1026707323109.us-central1.run.app" rel="noopener noreferrer"&gt;https://crucible-console-1026707323109.us-central1.run.app&lt;/a&gt;&lt;br&gt;
Source: &lt;a href="https://github.com/AshrafAhmed9/crucible-agent-security" rel="noopener noreferrer"&gt;https://github.com/AshrafAhmed9/crucible-agent-security&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Real per-agent service-account identity so the privilege-escalation finding reflects&lt;br&gt;
an actual IAM boundary rather than a hardcoded tool name, OpenTelemetry traces linked&lt;br&gt;
from the dashboard, and more third-party targets — the Google finding was the single&lt;br&gt;
highest-leverage hour in this whole build, and there's no reason to stop at one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built solo for the All Things Agentic Hackathon (Google Cloud, Gemini, ADK) —&lt;br&gt;
Fortified Enterprise Fleet track.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
  </channel>
</rss>
