<?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</title>
    <description>The most recent home feed on DEV Community.</description>
    <link>https://dev.to</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed"/>
    <language>en</language>
    <item>
      <title>The Hard Part of Leaving `request` is the App Built Around It</title>
      <dc:creator>Prithwiraj Bose</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:41:25 +0000</pubDate>
      <link>https://dev.to/sribasu/the-hard-part-of-leaving-request-is-the-app-built-around-it-4d61</link>
      <guid>https://dev.to/sribasu/the-hard-part-of-leaving-request-is-the-app-built-around-it-4d61</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I maintain &lt;a href="https://www.npmjs.com/package/request-to-axios" rel="noopener noreferrer"&gt;request-to-axios&lt;/a&gt;. This is a migration guide from the perspective of someone maintaining legacy Node.js code, not an independent review of my own package.&lt;/p&gt;

&lt;p&gt;When a project uses &lt;code&gt;request&lt;/code&gt;, replacing the dependency can look like a one-line change. The hard part usually isn't translating &lt;code&gt;request.get()&lt;/code&gt; to &lt;code&gt;axios.get()&lt;/code&gt;. It's finding all the assumptions accumulated around the old call: callbacks that expect &lt;code&gt;(error, response, body)&lt;/code&gt;, stream piping, &lt;code&gt;formData&lt;/code&gt;, &lt;code&gt;qs&lt;/code&gt;, cookies, default headers, odd redirects, and tests that depend on the response being text unless &lt;code&gt;json&lt;/code&gt; is enabled.&lt;/p&gt;

&lt;p&gt;A broad rewrite can turn a small security task into a risky application migration. That is why I built a compatibility wrapper around Axios: to make an incremental transition possible for common request patterns, while keeping unsupported behavior visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Dependency Deserves Attention
&lt;/h2&gt;

&lt;p&gt;The latest upstream &lt;code&gt;request&lt;/code&gt; release is still &lt;code&gt;2.88.2&lt;/code&gt;. The maintainers marked the project deprecated in 2020 and say no new changes are expected. That fact alone does not mean every application is exploitable. The more useful question is what versions your install resolves and whether your code reaches an affected behavior.&lt;/p&gt;

&lt;p&gt;On 2026-11-02, I installed &lt;code&gt;request@2.88.2&lt;/code&gt; into a temporary project and ran &lt;code&gt;npm audit&lt;/code&gt;. It resolved &lt;code&gt;form-data@2.3.3&lt;/code&gt;, &lt;code&gt;qs@6.5.5&lt;/code&gt;, &lt;code&gt;tough-cookie@2.5.0&lt;/code&gt;, and &lt;code&gt;uuid@3.4.0&lt;/code&gt;, alongside the deprecated request package. npm reported five vulnerable package nodes, with multiple advisories applying to some nodes.&lt;/p&gt;

&lt;p&gt;A few examples from that graph:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/advisories/GHSA-p8p7-x288-28g6" rel="noopener noreferrer"&gt;&lt;code&gt;CVE-2023-28155&lt;/code&gt;&lt;/a&gt; is an SSRF mitigation bypass in &lt;code&gt;request&lt;/code&gt; through 2.88.2 involving cross-protocol redirects. It matters when an application relies on URL or redirect restrictions to protect requests to internal services.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/advisories/GHSA-fjxv-7rqg-78g4" rel="noopener noreferrer"&gt;&lt;code&gt;CVE-2025-7783&lt;/code&gt;&lt;/a&gt; affects old &lt;code&gt;form-data&lt;/code&gt; boundary generation. Exploitation depends on an attacker being able to observe &lt;code&gt;Math.random()&lt;/code&gt; outputs and influence multipart content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/advisories/GHSA-hmw2-7cc7-3qxx" rel="noopener noreferrer"&gt;&lt;code&gt;CVE-2026-12143&lt;/code&gt;&lt;/a&gt; concerns CRLF injection through untrusted multipart field names or filenames in affected &lt;code&gt;form-data&lt;/code&gt; versions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/advisories/GHSA-72xf-g2v4-qvf3" rel="noopener noreferrer"&gt;&lt;code&gt;CVE-2023-26136&lt;/code&gt;&lt;/a&gt; is a &lt;code&gt;tough-cookie&lt;/code&gt; prototype-pollution issue, with a specific cookie-jar configuration precondition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also &lt;code&gt;qs&lt;/code&gt; and &lt;code&gt;uuid&lt;/code&gt; advisories in the resolved tree. Their practical impact depends on the application's own parse/stringify flow or UUID API use. A dependency audit is a signal to investigate, not proof that a particular endpoint is exploitable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Not Just Translate Every Call to Axios?
&lt;/h2&gt;

&lt;p&gt;A direct rewrite changes more than syntax. Axios returns a promise and a response object with &lt;code&gt;data&lt;/code&gt;; &lt;code&gt;request&lt;/code&gt; commonly uses a callback and passes the body as a separate argument. The projects may also differ on redirects, streaming, cookie jars, timeout details, form serialization, and error handling. Those differences are where the regression work hides.&lt;/p&gt;

&lt;p&gt;For a large legacy codebase, the safer sequence is usually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inventory the actual options and helper patterns in use.&lt;/li&gt;
&lt;li&gt;Add characterization tests around important request and response behavior.&lt;/li&gt;
&lt;li&gt;Replace the transport behind the current import name.&lt;/li&gt;
&lt;li&gt;Migrate unsupported edge cases separately, with explicit tests.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a gradual trial, npm supports an alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;request@npm:request-to-axios
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Existing &lt;code&gt;require('request')&lt;/code&gt; statements can continue resolving while the installed implementation comes from the wrapper. A representative callback call looks familiar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.test/items&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;qs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Compatibility Layer, Not a Security Guarantee
&lt;/h2&gt;

&lt;p&gt;The wrapper covers common callback/stream usage, method helpers, defaults, query strings, JSON, URL-encoded and multipart forms, immediate Basic/Bearer auth, redirects, a small in-memory cookie jar, TLS settings, and common transport options. It does &lt;strong&gt;not&lt;/strong&gt; implement OAuth/Hawk/AWS/HTTP signing, HAR import, digest retries, &lt;code&gt;multipart/related&lt;/code&gt;, or exact legacy redirect semantics. The cookie jar is deliberately limited and does not replace a full browser cookie implementation.&lt;/p&gt;

&lt;p&gt;That distinction matters. Migrating off an unmaintained client removes one set of risks; it does not make an application secure by itself. Review redirect destinations, validate user-controlled URLs, keep TLS verification enabled, and run &lt;code&gt;npm audit&lt;/code&gt; on the resulting dependency graph. Add tests for the options your service actually uses before deploying the alias.&lt;/p&gt;

&lt;p&gt;The package and its current compatibility notes are on &lt;a href="https://www.npmjs.com/package/request-to-axios" rel="noopener noreferrer"&gt;npm&lt;/a&gt; and &lt;a href="https://github.com/prithwirajbose/request-to-axios" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If a legacy option is important to your migration, check the documented limits first and open an issue with a minimal example.&lt;/p&gt;

</description>
      <category>node</category>
      <category>security</category>
      <category>javascript</category>
      <category>npm</category>
    </item>
    <item>
      <title>Giving an AI agent a wallet without giving it your keys</title>
      <dc:creator>Ahmad Shawar</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:41:25 +0000</pubDate>
      <link>https://dev.to/ahmad_shawar_de8d35d546cf/giving-an-ai-agent-a-wallet-without-giving-it-your-keys-407k</link>
      <guid>https://dev.to/ahmad_shawar_de8d35d546cf/giving-an-ai-agent-a-wallet-without-giving-it-your-keys-407k</guid>
      <description>&lt;p&gt;Agents are starting to pay for things. An agent buying API credits, renting a GPU for an hour or paying for a dataset is no longer a thought experiment, and x402 (HTTP &lt;code&gt;402 Payment Required&lt;/code&gt; with on-chain payment) makes it a normal web request.&lt;/p&gt;

&lt;p&gt;That leaves the question of how the agent holds money.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two bad options
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Give the agent a private key.&lt;/strong&gt; It works until a prompt injection, a bug or a leaked environment file. Then the wallet is empty, and there is nothing between the key and the funds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approve every payment by hand.&lt;/strong&gt; Safe, and it removes the reason to use an agent.&lt;/p&gt;

&lt;p&gt;What people actually want is what they already do with a company card: a limit per purchase, a monthly budget, a list of places it works, and a phone call for anything unusual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the limits where the agent can't reach them
&lt;/h2&gt;

&lt;p&gt;The limits have to live somewhere the agent, and the machine it runs on, can't change. A smart contract is a good fit: the rules are checked by every node, and changing them needs the owner's key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ahmad-codex/purser" rel="noopener noreferrer"&gt;Purser&lt;/a&gt; is an ERC-4337 smart account built for this. The owner grants each agent a session key with a policy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an allow-list of contracts and functions it may call&lt;/li&gt;
&lt;li&gt;a cap per payment and a budget per period, per token&lt;/li&gt;
&lt;li&gt;a validity window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside the policy, the agent pays on its own. Over the limit, the payment becomes an approval request, and it runs only if the owner co-signs. One transaction revokes a key or freezes the whole account.&lt;/p&gt;

&lt;p&gt;If the agent's key leaks, the damage is bounded: the rest of the current budget, at allowed places, until you revoke it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that was harder than it looks
&lt;/h2&gt;

&lt;p&gt;ERC-4337 splits an operation into validation and execution, and validation is not allowed to read the clock (ERC-7562), because bundlers have to be able to simulate it reliably. A daily budget is all about the clock.&lt;/p&gt;

&lt;p&gt;So the checks are split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validation:&lt;/strong&gt; signature, validity window, allow-list and per-payment cap. A disallowed call fails here, before it costs anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution:&lt;/strong&gt; the rolling budget, in &lt;code&gt;executeUserOp&lt;/code&gt;, where reading the block time is fine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two smaller rules that matter: an owner approval raises the amount but never the scope, so an approved payment still has to be to an allowed place; and a revoke earlier in a bundle still stops a later operation in the same bundle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing money code
&lt;/h2&gt;

&lt;p&gt;Unit tests aren't enough for this. Purser has 41 unit tests through a real EntryPoint, fuzz tests that compare random payment and time sequences against a simple model of the budget, and invariant tests that throw thousands of random calls at the account and check three properties after each one: no spending over budget without approval, no funds moved by a revoked key, no policy change without the owner. Slither runs in CI.&lt;/p&gt;

&lt;p&gt;It's still early and not audited, which is why everything below runs on a local chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agents use it through MCP
&lt;/h2&gt;

&lt;p&gt;An MCP server exposes six tools: &lt;code&gt;wallet_status&lt;/code&gt;, &lt;code&gt;send_eth&lt;/code&gt;, &lt;code&gt;send_token&lt;/code&gt;, &lt;code&gt;call_contract&lt;/code&gt;, &lt;code&gt;get_request&lt;/code&gt; and &lt;code&gt;list_requests&lt;/code&gt;. Each payment returns one of three outcomes, written for the model: done with the budget left, waiting for the owner with a request id, or refused with a reason it can act on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:8787:8787 ghcr.io/ahmad-codex/purser:demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:8787" rel="noopener noreferrer"&gt;http://localhost:8787&lt;/a&gt;. The container starts a local chain, deploys everything, and plays the agent story while the console updates. Then connect your own agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http purser http://localhost:8787/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and ask it to pay the merchant 0.3 ETH.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/ahmad-codex/purser/blob/main/ROADMAP.md" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; starts with paying x402 endpoints within the budget, a gas budget per key and EIP-7702 support. It's MIT licensed, and there are good first issues open. If you let agents spend money today, I'd like to hear how you limit it.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>security</category>
      <category>web3</category>
    </item>
    <item>
      <title>I Fact-Checked Every Finding an AI Security Reviewer Gave Me. Here's What Held Up.</title>
      <dc:creator>Amirthavarshini Marimuthu</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:40:57 +0000</pubDate>
      <link>https://dev.to/amir09/i-fact-checked-every-finding-an-ai-security-reviewer-gave-me-heres-what-held-up-e2k</link>
      <guid>https://dev.to/amir09/i-fact-checked-every-finding-an-ai-security-reviewer-gave-me-heres-what-held-up-e2k</guid>
      <description>&lt;p&gt;During my internship at RakFort, one of my tasks was simple to describe and slow to do: &lt;strong&gt;run every security check in &lt;a href="https://github.com/secfoo-com/secfoo" rel="noopener noreferrer"&gt;Secfoo&lt;/a&gt; with the Claude agent, and then check whether the AI was actually right.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not "did the run finish". Not "does the report look good". Is each finding &lt;em&gt;true&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;This post is about what I found, and what I'd tell anyone who is starting to use AI for security reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick background: what Secfoo is
&lt;/h2&gt;

&lt;p&gt;Secfoo is an open-source tool that turns the AI coding agent you already use (Claude Code, Codex, Gemini CLI, Cursor, GitHub Copilot and others) into a security reviewer.&lt;/p&gt;

&lt;p&gt;You point it at your code, pick a check, and it gives the AI clear instructions and a fixed report format. You get back a structured report with findings, severity and recommendations, and everything shows up in a local dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;secfoo run &lt;span class="nt"&gt;--skill&lt;/span&gt; deployment-readiness &lt;span class="nt"&gt;--agent&lt;/span&gt; claude &lt;span class="nt"&gt;--target&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
secfoo serve   &lt;span class="c"&gt;# open the dashboard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has 9 checks, including SAST, threat modeling, secret scanning, dependency triage, deployment readiness and responsible AI compliance.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I tested
&lt;/h2&gt;

&lt;p&gt;My target was Secfoo's own codebase (a good test, because I could read every file the AI talked about).&lt;/p&gt;

&lt;p&gt;For each report I:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Opened every finding&lt;/li&gt;
&lt;li&gt;Went to the exact file and line it pointed to&lt;/li&gt;
&lt;li&gt;Checked the code &lt;strong&gt;as it was on the day of the scan&lt;/strong&gt; (using the commit from that date, not today's code)&lt;/li&gt;
&lt;li&gt;Marked it &lt;strong&gt;Confirmed&lt;/strong&gt;, &lt;strong&gt;Partly wrong&lt;/strong&gt; or &lt;strong&gt;Wrong&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Checked that the numbers on the dashboard matched the report&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 3 matters more than I expected. Code changes every day. If you check an old report against today's code, you'll blame the AI for things that were true at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deployment readiness: 6 of 7 fully correct
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;F1&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Local dashboard has no login or CSRF protection&lt;/td&gt;
&lt;td&gt;✅ Confirmed (exact lines were right)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F2&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;No security scanning in CI&lt;/td&gt;
&lt;td&gt;⚠️ Partly wrong&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F3&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Release actions pinned by tag, long-lived tokens&lt;/td&gt;
&lt;td&gt;✅ Confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F4&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Uploads saved to disk before the size check&lt;/td&gt;
&lt;td&gt;✅ Confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F5&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Docker image runs as root, base image not pinned&lt;/td&gt;
&lt;td&gt;✅ Confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F6&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;No health endpoint&lt;/td&gt;
&lt;td&gt;✅ Confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F7&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Dependencies have no upper version pins&lt;/td&gt;
&lt;td&gt;✅ Confirmed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Responsible AI compliance: 4 of 4 correct
&lt;/h3&gt;

&lt;p&gt;All four findings were accurate, and the overall rating ("Low") made sense for a tool that doesn't make decisions about people.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interesting one: F2
&lt;/h2&gt;

&lt;p&gt;Most of F2 was right. CI really didn't run any security scanners, and the linter was set to never fail the build.&lt;/p&gt;

&lt;p&gt;But the report also said the release workflow &lt;strong&gt;"runs on any v* tag push"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It didn't. The workflow had been changed to &lt;strong&gt;manual-only&lt;/strong&gt; five days before the scan. The file even had a comment at the top explaining the change.&lt;/p&gt;

&lt;p&gt;So the AI described how the project &lt;em&gt;used to&lt;/em&gt; work. My guess is that it matched a very common pattern ("release on tag push") instead of reading the current trigger carefully.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of mistake that is easy to miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It sounds completely reasonable&lt;/li&gt;
&lt;li&gt;It's in a well-formatted report next to six correct findings&lt;/li&gt;
&lt;li&gt;It's only wrong in one detail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If I had just skimmed the report, I would have believed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I tested besides the reports
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bad input.&lt;/strong&gt; I fed the CLI things a real user might get wrong: a folder that doesn't exist, a file instead of a folder, an unknown skill or agent name, a GitHub repo that doesn't exist. Every one gave a clear error, with no crash and no AI tokens wasted. I found two small issues (a negative &lt;code&gt;--timeout&lt;/code&gt; was accepted, and an empty target quietly scanned the current folder) and reported them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The dashboard.&lt;/strong&gt; All pages loaded and the finding counts matched the reports, except the home page, which crashed with a 500 error. The cause was a recent change: agents that don't report cost now store "unknown" instead of $0, and the home page added the costs together with a plain &lt;code&gt;sum()&lt;/code&gt;, which fails on an empty value. It was a one-line fix, and my PR for it (&lt;a href="https://github.com/secfoo-com/secfoo/pull/31" rel="noopener noreferrer"&gt;#31&lt;/a&gt;) is now merged.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. AI reviewers are genuinely useful.&lt;/strong&gt; Most findings were correct, with the right file and line numbers. For coverage and speed, it's a huge help, especially for a small team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. "Looks professional" is not the same as "true".&lt;/strong&gt; The one wrong detail was written just as confidently as the correct ones. Severity labels and neat tables don't make a finding correct.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Check against the right version of the code.&lt;/strong&gt; Use the commit from the scan date. Otherwise you'll mark correct findings as wrong (or the other way round).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Keep a human in the loop for anything that matters.&lt;/strong&gt; If a report is going to someone who will sign it off, every finding should be checked first. It took me a while, but it's much faster than reviewing the code from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Secfoo is free and open source (MIT). If you're a student or developer interested in security, try it on your own project and check the findings yourself. That's honestly the best way to learn what AI reviewers are good and bad at.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/secfoo-com/secfoo" rel="noopener noreferrer"&gt;https://github.com/secfoo-com/secfoo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, issues and contributions are welcome. I'd love to hear how it does on your code!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is my second post about Secfoo. The first one was about &lt;a href="https://dev.to/amir09/secfoo-i-caught-our-security-scanner-inventing-fake-vulnerabilities-heres-the-proof-1hak"&gt;catching an AI scanner inventing fake vulnerabilities&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  security #ai #opensource #testing
&lt;/h1&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>opensource</category>
      <category>security</category>
    </item>
    <item>
      <title>CVE-2026-105483 remediation checklist for Node.js teams</title>
      <dc:creator>kozhevniko</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:40:14 +0000</pubDate>
      <link>https://dev.to/kozhevniko/cve-2026-105483-remediation-checklist-for-nodejs-teams-818</link>
      <guid>https://dev.to/kozhevniko/cve-2026-105483-remediation-checklist-for-nodejs-teams-818</guid>
      <description>&lt;h1&gt;
  
  
  CVE-2026-105483 remediation checklist for Node.js teams
&lt;/h1&gt;

&lt;p&gt;The fastest accurate response to CVE-2026-105483 starts with the runtime version and ends with evidence that the deployed client rejects the wrong certificate identity. The bug affects Node.js 24.x before 24.22.1 and 26.x before 26.12.1. During TLS verification, a fullwidth-digit IPv4 destination could be normalized and resolved as an address while DNS names were checked against the certificate. A trusted certificate with a matching DNS SAN could authenticate an IP endpoint without an IP SAN.&lt;/p&gt;

&lt;p&gt;Node.js fixed the issue on October 21, 2026. It is rated High, with CVSS v3.0 7.4 and CWE-295. The checklist below separates the mandatory runtime fix from application hardening and assurance work.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Identify the running runtime
&lt;/h2&gt;

&lt;p&gt;List every Node.js process that performs TLS or embeds a runtime. Record the exact version, artifact digest, environment, owner, and deployment time. Check containers, packaged executables, desktop tools, CI utilities, and appliances in addition to web services.&lt;/p&gt;

&lt;p&gt;Do not close the inventory on a lockfile alone. Verify the process or the signed package that actually runs. A base-image name and an application dependency can both disagree with the executable serving traffic.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Upgrade the affected range
&lt;/h2&gt;

&lt;p&gt;Move 24.x systems to 24.22.1 or later and 26.x systems to 26.12.1 or later. Rebuild images and redistributed packages. For single executable applications, verify the embedded runtime version in the new build.&lt;/p&gt;

&lt;p&gt;Replace old workers, sidecars, and long-lived processes. Confirm the fixed runtime is active after rollout and retain the runtime evidence with the release record.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Find security-sensitive destinations
&lt;/h2&gt;

&lt;p&gt;Review clients that accept a destination from tenants, users, integrations, configuration APIs, queues, or imported records. Prioritize clients that send credentials, administrative commands, private data, or signed requests.&lt;/p&gt;

&lt;p&gt;For each client, record whether the intended destination is a DNS name, an IP address, or both. Then trace normalization and validation to the exact TLS call. A policy that checks one string while the client connects with another is not a complete control.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Narrow destination input
&lt;/h2&gt;

&lt;p&gt;Allow approved ASCII DNS names or canonical IP literals. Reject ambiguous fullwidth-digit forms, mixed representations, and unapproved redirects before invoking the TLS client. Require a DNS SAN for a DNS identity and an IP address SAN for an IP endpoint.&lt;/p&gt;

&lt;p&gt;Avoid custom &lt;code&gt;checkServerIdentity&lt;/code&gt; callbacks that accept a certificate based on a display label, a Common Name, or a substring. If a callback is necessary, preserve the correct SAN class and all standard certificate validation.&lt;/p&gt;

&lt;p&gt;This input policy is supporting mitigation. The patched runtime remains mandatory.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Review trust anchors
&lt;/h2&gt;

&lt;p&gt;Identify which CAs can issue certificates to the affected clients. Include internal roots, test roots, delegated intermediates, and service-mesh trust bundles. Ask whether any of those authorities can issue an address-like DNS SAN that ships inside a trusted chain.&lt;/p&gt;

&lt;p&gt;Limit client trust to the authorities required for its destinations. A broad trust store increases the practical conditions for the vulnerability and complicates incident analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Test the identity boundary
&lt;/h2&gt;

&lt;p&gt;Use a private test CA and a local endpoint. Create a certificate with a numeric DNS SAN and no matching IP SAN. Connect with a fullwidth-digit host that resolves to the test address. The fixed runtime should reject the certificate because the endpoint is an IP address.&lt;/p&gt;

&lt;p&gt;Add positive controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A matching IP SAN should succeed for the IP endpoint.&lt;/li&gt;
&lt;li&gt;A normal DNS SAN should succeed for an approved DNS name.&lt;/li&gt;
&lt;li&gt;An unapproved destination should fail application policy before TLS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the test in the actual deployable artifact. Keep the fixtures versioned so a certificate change cannot weaken the test silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Record exposure correctly
&lt;/h2&gt;

&lt;p&gt;At 04:17 +08:00 on November 2, 2026, ZoomEye Search &lt;code&gt;app="Node.js"&lt;/code&gt; returned 5,539,674 matches. Filter &lt;code&gt;vul.cve="CVE-2026-105483"&lt;/code&gt; returned zero. Exposure is 5,539,674 Node.js product fingerprints, not confirmed vulnerable assets.&lt;/p&gt;

&lt;p&gt;Use the external count for population context. Use runtime, destination policy, certificate trust, and business authority for prioritization. Do not describe a fingerprint as a victim.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Monitor after the change
&lt;/h2&gt;

&lt;p&gt;Log certificate identity failures, destination policy rejections, runtime versions, and changes to destination configuration. Distinguish a DNS failure, a chain failure, and a SAN mismatch. Alert on the introduction of previously unapproved destination forms or trust anchors.&lt;/p&gt;

&lt;p&gt;If evidence indicates that a client reached an unintended endpoint, preserve the configuration and connection records, determine what data crossed the session, and follow the credential-rotation and incident process. The advisory does not state that exploitation has occurred; the organization must reach its own conclusion from its evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Close with proof
&lt;/h2&gt;

&lt;p&gt;An affected service is ready when the running artifact reports a fixed Node.js version, the test proves the correct SAN class is enforced, the destination input policy is deployed, and the old process is no longer serving traffic. Save those artifacts with the change record so a later reviewer can distinguish a patched runtime from a clean-looking package manifest.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/blog/vulnerability/october-2026-security-releases" rel="noopener noreferrer"&gt;Node.js October 21, 2026 Security Releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/blog/release/v24.22.1/" rel="noopener noreferrer"&gt;Node.js 24.22.1 release notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/blog/release/v26.12.1/" rel="noopener noreferrer"&gt;Node.js 26.12.1 release notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/advisories/GHSA-8h4p-qpcq-gq24" rel="noopener noreferrer"&gt;GitHub Advisory GHSA-8h4p-qpcq-gq24&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zoomeye.ai/searchResult?q=YXBwPSJOb2RlLmpzIg%3D%3D" rel="noopener noreferrer"&gt;ZoomEye Search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cve2026105483</category>
      <category>node</category>
      <category>tls</category>
      <category>certificatevalidation</category>
    </item>
    <item>
      <title>H3 Martial-Arts and TaoMate Workflows: Read the Schedule, Not the Filename</title>
      <dc:creator>AI-KSK</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:32:08 +0000</pubDate>
      <link>https://dev.to/ai-ksk/h3-martial-arts-and-taomate-workflows-read-the-schedule-not-the-filename-2n9c</link>
      <guid>https://dev.to/ai-ksk/h3-martial-arts-and-taomate-workflows-read-the-schedule-not-the-filename-2n9c</guid>
      <description>&lt;p&gt;An eight-step filename is not an eight-step execution trace. Equally, a three-step scheduler can be genuinely configured without proving a particular speedup. These two H3 exports illustrate both distinctions.&lt;/p&gt;

&lt;p&gt;The package contains two JSON workflows: a martial-arts two-pass graph with 113 nodes and a TaoMate example collection with 239 nodes. Together they have 396 explicit links, plus named Set/Get relationships in the first file. This is a static walkthrough, not a new inference, audio review or hardware benchmark.&lt;/p&gt;

&lt;p&gt;The source title mentions 1080p and nearly one second per frame. Those remain source claims, not results measured for this guide. Export frame rate is not generation throughput.&lt;/p&gt;

&lt;h2&gt;
  
  
  01 — Resolve named inputs before counting references
&lt;/h2&gt;

&lt;p&gt;The martial-arts graph uses SetNode/GetNode pairs rather than direct visible wires for many inputs. Three image loaders are active: 159, 200 and 203. Their Set nodes publish &lt;code&gt;IMAGE_0&lt;/code&gt;, &lt;code&gt;IMAGE_1&lt;/code&gt; and &lt;code&gt;IMAGE_2&lt;/code&gt;; the corresponding getters reach the first three reference-image slots of conditioner 136.&lt;/p&gt;

&lt;p&gt;Other image providers, all video providers and all source-audio providers are bypassed. Their getters can still be enabled and wired. Counting every visible getter would therefore overstate the active reference set.&lt;/p&gt;

&lt;p&gt;Check the compatible frontend's handling of named values and bypassed providers on import. The saved graph does not prove that every optional getter will resolve correctly in every installation.&lt;/p&gt;

&lt;p&gt;The prompt takes a similar route: active prompt node 194 feeds concatenation, then the live output of ShowText 297 feeds the named positive value and its getter. Extra prompt node 309 is bypassed. A cached ShowText string or the conditioner's old text is not an independent active prompt source.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scheduler receives 20, not the eight-step title
&lt;/h2&gt;

&lt;p&gt;PrimitiveInt 300 stores 20. It publishes the named value &lt;code&gt;s&lt;/code&gt;, retrieved by node 401 and connected to BasicScheduler's steps input. That overrides the scheduler's saved local value of 10.&lt;/p&gt;

&lt;p&gt;The resulting sigma schedule passes through H3SigmaRefiner 361. Its named controls store extra_steps 1, start_at_sigma approximately 0.6, end_at_sigma 0 and cosine spacing. Both sampling stages receive the same refiner output.&lt;/p&gt;

&lt;p&gt;Do not turn this into a guessed 20+1 evaluation count: the custom refiner's implementation and sampler execution were not inspected or run. What the graph establishes is a linked 20-step input before transformation, not a verified eight-step run, an 8+8 split or a measured total NFE.&lt;/p&gt;

&lt;p&gt;The active Ref2V eight-step LoRA is a separate model selection. Its filename does not override that connected scheduler input. The alternative FL2V eight-step LoRA is bypassed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the model stack as a sequence
&lt;/h2&gt;

&lt;p&gt;The selected base is &lt;code&gt;minimax_h3_hybrid_fl2va_ref2va_b25-49-bf16-v1.01.safetensors&lt;/code&gt;, with the selected INT8/ConvRot-named Qwen text encoder, FP16 video VAE and FP32 audio VAE.&lt;/p&gt;

&lt;p&gt;After the attention utilities and active Ref2V Turbo selection, Motion Repair is applied model-only at a linked strength of 0.2. The subsequent stack includes spatial-physics at model strength 0.3, wushu-e3 at 0.75, and another Motion Repair application at 0.5. Those final three LoraLoader nodes also store CLIP strength 1.&lt;/p&gt;

&lt;p&gt;The two Motion Repair applications should not be silently rewritten as one verified equivalent strength. Their positions and loader types differ. Likewise, attention and low-VRAM node names are not measured evidence of a particular kernel or memory reduction.&lt;/p&gt;

&lt;p&gt;The saved active media are images rather than a source motion-video sequence. This is reference conditioning plus model modifications and a prompt, not an explicit pose-map lock or proof of precise martial-arts motion transfer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The learned-upscale node does not promise a larger raster
&lt;/h2&gt;

&lt;p&gt;The coarse resolution selector requests 4:3, 1 megapixel and alignment to 32. Named width/height links override the conditioner's old 1344×768 values.&lt;/p&gt;

&lt;p&gt;The learned latent upscaler is also configured in &lt;strong&gt;megapixels mode targeting 1 MP&lt;/strong&gt;, with alignment 32, CUDA, BF16 and chunking enabled. Its presence alone does not establish 2× enlargement, 1080p or a higher pixel count than the first stage. Inspect actual decoded dimensions.&lt;/p&gt;

&lt;p&gt;The duration control is 10 and feeds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max(5, round(a * 24))
+ (5 - (max(5, round(a * 24)) % 17)) % 17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arithmetic gives 243 requested frames, overriding the old 124-frame value. At configured 24 fps that is a nominal 10.125 seconds, not a measured output duration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two sampling stages, two different first-stage outputs
&lt;/h2&gt;

&lt;p&gt;The first sampler's &lt;code&gt;DENOISED_OUTPUT&lt;/code&gt; is split into video and audio latents. Only video passes through the learned upscaler; audio is carried into the concatenated second-stage latent.&lt;/p&gt;

&lt;p&gt;The second sampler reuses the same guider, positive conditioning and transformed sigma schedule. There is no separate rebuilt high-resolution conditioner in this graph. Carrying the audio latent forward does not prove that the final audio remains unchanged after another sampling stage.&lt;/p&gt;

&lt;p&gt;The first-stage save uses the first sampler's &lt;code&gt;OUTPUT&lt;/code&gt;, not the &lt;code&gt;DENOISED_OUTPUT&lt;/code&gt; sent toward upscaling. The second save uses the second sampler's &lt;code&gt;OUTPUT&lt;/code&gt;. Each is routed into video and audio decoders, so this is not direct source-audio muxing.&lt;/p&gt;

&lt;p&gt;Both VHS save nodes use the prefix &lt;code&gt;H3_Ref2VA二采&lt;/code&gt;, despite belonging to different stages. Both store 24 fps, H.264, CRF 19 and trim_to_audio false. Identify the stage through connections, not that shared filename prefix. Compatibility of the audiovisual latent/decoder path and actual saved files still requires a test.&lt;/p&gt;

&lt;h2&gt;
  
  
  02 — Seven TaoMate examples are not seven working I2V runs
&lt;/h2&gt;

&lt;p&gt;The second JSON contains seven repeated branches. The letters below are audit labels, not authored project names or seven separately supplied workflow files.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Branch&lt;/th&gt;
&lt;th&gt;Saved state&lt;/th&gt;
&lt;th&gt;What needs attention&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;Entire branch bypassed&lt;/td&gt;
&lt;td&gt;No active generation or save should be claimed from its stored controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;Main branch enabled, 9:16&lt;/td&gt;
&lt;td&gt;Full selected LoRA stack with a connected first-frame image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;Main branch enabled, 9:16&lt;/td&gt;
&lt;td&gt;Similar stack, but not automatically a controlled comparison with B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;Main branch enabled, 16:9&lt;/td&gt;
&lt;td&gt;First-frame image loader is bypassed; do not label it assured I2V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;Mixed enabled/bypassed nodes, 16:9&lt;/td&gt;
&lt;td&gt;Save remains enabled while core generation/decoding is bypassed; inspect before queueing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;F&lt;/td&gt;
&lt;td&gt;Main branch enabled, 3:4&lt;/td&gt;
&lt;td&gt;TaoMate and base wushu selections active; optional stack bypassed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G&lt;/td&gt;
&lt;td&gt;Main branch enabled, 3:4&lt;/td&gt;
&lt;td&gt;Newer wushu-action selection plus reference audio; Bunny selection bypassed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;An enabled SaveVideo node is not proof of a functioning upstream generation path. In particular, E needs review rather than being counted as a completed or successful example. Nor does static inspection alone certify that import will fail: verify the actual node/frontend behavior in a working copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three steps are configured, but speed is unmeasured
&lt;/h2&gt;

&lt;p&gt;Enabled main branches B, C, D, F and G use schedulers storing simple, 3 steps and denoise 1, with Euler selection. That three-step setting should not be dismissed merely because it has not been benchmarked.&lt;/p&gt;

&lt;p&gt;Their SelfLift controls store CFG 1, transition step 1, low-resolution scale 0.4, rho 0, weights 0.5–1 and the BF16 learned latent upscaler, with fixed seed control. These values do not prove actual intermediate dimensions, total model evaluations or latency. Extra seed-control widgets must not be mechanically zipped into named execution parameters.&lt;/p&gt;

&lt;p&gt;TaoMate's filename contains &lt;code&gt;step3000&lt;/code&gt;; wushu filenames contain other step-like numbers. Those strings do not set inference steps.&lt;/p&gt;

&lt;p&gt;Model strengths come from linked PrimitiveFloat controls. The full B/C stack includes TaoMate 1, wushu 0.75, Combat and camera-motion at 0.35 each, spatial-physics 0.3, Motion Repair 0.2 and Bunny 0.1. D/F keep only TaoMate and the base wushu selection active. G substitutes the newer wushu-action file and leaves Bunny bypassed.&lt;/p&gt;

&lt;p&gt;These are different configurations and inputs, not a new matched speed or quality study.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dimensions and soundtrack still need separate checks
&lt;/h2&gt;

&lt;p&gt;All seven selectors store 1.4 MP and multiple 32, with the aspect ratios shown above. Connected dimensions override old local 1344×768 values. Do not promise fixed 1080p output from those controls.&lt;/p&gt;

&lt;p&gt;The linked duration expressions use the same nominal 10-to-243 arithmetic described earlier. CreateVideo stores 24 fps, 8-bit and sRGB controls; actual output dimensions, length and codec selection need inspection.&lt;/p&gt;

&lt;p&gt;Only G has a loaded audio connection, and it enters the &lt;strong&gt;reference-audio conditioning port&lt;/strong&gt;. It is not drive_audio, final_audio or a direct soundtrack connection. All CreateVideo audio inputs come from sampled-audio decoders.&lt;/p&gt;

&lt;p&gt;That distinction matters for voice or lip-sync requirements. An audio reference does not prove the original waveform is preserved, the same spoken content is reproduced, or the output lips align correctly. Listen to the result rather than treating the input connection as acceptance evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before publishing results
&lt;/h2&gt;

&lt;p&gt;Resolve the exact model and custom-node versions. Inspect the named routes in the first file and the mixed branch states in the second. Choose intended outputs, check effective prompts and dimensions, and run a small authorized-media test before accepting any claim about motion, identity, texture, audio or speed.&lt;/p&gt;

&lt;p&gt;The new first-file copy removes only five historical video-preview fields; the second-file bytes are unchanged. Source originals are preserved. Covers are selected assets, not visually verified test results, and model weights/input media are not supplied here.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.youtube.com/watch?v=bXFhG_OlEUU" rel="noopener noreferrer"&gt;source-provided tutorial&lt;/a&gt; is recorded without live verification. Check workflow, model, LoRA, node, image, audio and cover rights separately. No publishing, runtime certification or blanket commercial license is included with this source-based walkthrough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting the workflows
&lt;/h2&gt;

&lt;p&gt;Published by this channel. The graphs are free; weights, LoRAs and input assets are separate and carry their own terms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hugging Face:&lt;/strong&gt; &lt;a href="https://huggingface.co/AI-KSK/minimax-h3-martial-taomate-305" rel="noopener noreferrer"&gt;AI-KSK/minimax-h3-martial-taomate-305&lt;/a&gt; — two JSONs, covers, SHA256 manifest. &lt;strong&gt;Start here.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ModelScope (魔搭):&lt;/strong&gt; &lt;a href="https://www.modelscope.cn/models/Sunjian520/minimax-h3-martial-taomate-305" rel="noopener noreferrer"&gt;Sunjian520/minimax-h3-martial-taomate-305&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Civitai:&lt;/strong&gt; &lt;a href="https://civitai.com/models/2942484" rel="noopener noreferrer"&gt;8-step Wushu Motion Control&lt;/a&gt; · &lt;a href="https://civitai.com/models/2942481" rel="noopener noreferrer"&gt;TaoMate 3-step LoRA&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run without a local GPU:&lt;/strong&gt; &lt;a href="https://www.runninghub.ai/zh-cn/post/2100146680422281217?inviteCode=rh-v1111" rel="noopener noreferrer"&gt;01&lt;/a&gt; · &lt;a href="https://www.runninghub.ai/zh-cn/post/2100147178424578050?inviteCode=rh-v1111" rel="noopener noreferrer"&gt;02&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tutorial:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=bXFhG_OlEUU" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; · &lt;a href="https://www.bilibili.com/video/BV1MYec6uEoN" rel="noopener noreferrer"&gt;Bilibili&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>comfyui</category>
      <category>videogeneration</category>
      <category>workflows</category>
      <category>ai</category>
    </item>
    <item>
      <title>Cifrado de hardware en USB y discos: cómo saber si es real</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:30:40 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/cifrado-de-hardware-en-usb-y-discos-como-saber-si-es-real-3p63</link>
      <guid>https://dev.to/lu1tr0n/cifrado-de-hardware-en-usb-y-discos-como-saber-si-es-real-3p63</guid>
      <description>&lt;p&gt;Lenovo vendía una memoria USB con sensor de huella digital anunciada como cifrada. Un desarmado posterior, documentado en un &lt;a href="https://www.reddit.com/r/technology/comments/1xl2pr3/lenovos_encrypted_fingerprint_usb_drive_is_just/" rel="noopener noreferrer"&gt;hilo de Reddit&lt;/a&gt;, mostró que adentro no había más que una tarjeta microSD genérica: ningún chip criptográfico, ningún motor AES, nada que cifrara un solo byte. El sensor biométrico apenas desbloqueaba una aplicación de Windows; la memoria, leída directo con cualquier lector de tarjetas, entregaba los archivos en texto plano.&lt;/p&gt;

&lt;p&gt;El caso no es un bug aislado de un fabricante. Es el síntoma de un mercado entero donde la palabra 'cifrado' aparece en la caja sin que exista una propiedad verificable detrás. Esta nota explica qué hace real al cifrado de hardware, qué estándares lo certifican y cómo comprobarlo en cualquier USB o disco externo antes de confiarle datos sensibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El cifrado de hardware real exige un chip AES dedicado que cifra los datos antes de que lleguen a la memoria flash.- Un sensor de huella digital que solo desbloquea una app de Windows no cifra nada: la memoria sigue legible en cualquier lector de tarjetas.- FIPS 140-2 o FIPS 140-3 validados en el registro CMVP de NIST son la única prueba verificable de un módulo criptográfico real.- TCG Opal define cómo un SSD autocifrado protege la clave de los datos sin exponerla al sistema operativo.- Comandos como hdparm -I y sedutil-cli --scan revelan si un disco soporta y tiene activo el cifrado por hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es el cifrado de hardware?
&lt;/h2&gt;

&lt;p&gt;El cifrado de hardware es la técnica en la que un chip dedicado dentro del controlador de un disco o memoria USB cifra y descifra cada byte con AES antes de escribirlo o leerlo de la memoria flash, sin que el sistema operativo ni ningún programa intervengan en el proceso ni tengan acceso directo a la clave.&lt;/p&gt;

&lt;p&gt;La diferencia con el cifrado por software (BitLocker en modo estándar, VeraCrypt, LUKS) está en la ubicación de la clave y del cómputo. En el cifrado por software, el sistema operativo carga la clave en la RAM y usa el procesador principal para cifrar cada bloque. En una unidad autocifrada real, la clave vive dentro del controlador, y ni un volcado de memoria del equipo la expone.&lt;/p&gt;

&lt;p&gt;Un sensor de huella digital, por sí solo, no define nada sobre dónde ocurre el cifrado. Puede ser la llave de un cifrado legítimo, como en una unidad certificada, o puede ser apenas el gatillo de una ventana de inicio de sesión de una app, como en el caso de Lenovo. La huella identifica a la persona, pero no dice nada sobre qué le pasa a los datos después.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa
&lt;/h2&gt;

&lt;p&gt;El riesgo no es solo perder un archivo. Una empresa que compra 500 memorias USB 'cifradas' para su equipo de ventas y confía en esa palabra está exponiendo datos de clientes bajo una falsa sensación de cumplimiento normativo. Si el dispositivo se pierde y en realidad nunca cifró nada, cualquier marco regulatorio que exima de notificación a equipos cifrados deja de aplicar, y la empresa queda expuesta a una notificación de brecha que creía evitada.&lt;/p&gt;

&lt;p&gt;El sensor de huella no es una medida de seguridad, sino una cerradura decorativa sobre una memoria sin ninguna protección real, cuando el fabricante nunca implementó cifrado de hardware genuino.&lt;/p&gt;

&lt;p&gt;Esto no es exclusivo de pendrives baratos. En el pasado, investigaciones académicas sobre SSD comerciales que anunciaban cifrado por hardware hallaron implementaciones defectuosas que permitían evadir la clave sin conocer la contraseña, lo que llevó a Microsoft a dejar de confiar por defecto en el cifrado por hardware reportado por el propio disco para proteger volúmenes con BitLocker. El problema de fondo es siempre el mismo: una afirmación sin verificación independiente.&lt;/p&gt;

&lt;p&gt;El problema se repite fuera de los USB de bajo costo: discos externos, SSD portátiles y hasta algunos NAS domésticos usan la palabra 'cifrado' en el empaque sin publicar jamás un estándar, un algoritmo verificable o un número de certificación. La única forma de saber si hay algo real detrás es preguntar por el estándar, no por el adjetivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona por dentro
&lt;/h2&gt;

&lt;p&gt;Una unidad autocifrada (SED, por &lt;em&gt;self-encrypting drive&lt;/em&gt;) separa dos claves. La Media Encryption Key (MEK) es la que realmente cifra cada bloque de datos con AES, casi siempre en modo XTS. Esa clave se genera una sola vez, dentro del chip, y nunca sale de ahí.&lt;/p&gt;

&lt;p&gt;La segunda clave es la Key Encryption Key (KEK), derivada del PIN, la contraseña o, en dispositivos biométricos bien diseñados, de un secreto que el sensor de huella libera tras verificar la identidad. La KEK no cifra los datos: cifra a la MEK, que queda guardada en una zona reservada del disco. Sin la KEK correcta, la MEK sigue ahí, pero inutilizable.&lt;/p&gt;

&lt;p&gt;Esta separación es la que permite el borrado criptográfico instantáneo: descartar la MEK, sin tocar un solo bit de los datos reales, vuelve ilegible todo el contenido en milisegundos, porque ya no existe ninguna clave capaz de descifrarlo. Es el mecanismo detrás de funciones como 'borrado seguro' en SSD empresariales, y la razón por la que un disco de varios terabytes puede darse de baja de forma segura en segundos.&lt;br&gt;
El estándar TCG Opal, publicado por Trusted Computing Group, define cómo un SSD autocifrado gestiona su clave sin exponerla al sistema operativo.&lt;br&gt;
El estándar que define cómo deben comportarse estas piezas en un SSD o HDD es TCG Opal, publicado por el &lt;a href="https://trustedcomputinggroup.org/" rel="noopener noreferrer"&gt;Trusted Computing Group&lt;/a&gt;. Las memorias USB no siguen necesariamente Opal, pensado originalmente para SATA y NVMe, pero las serias documentan un esquema equivalente: un controlador con motor AES, una KEK derivada del PIN o la huella, y una MEK que nunca cruza el bus USB en claro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Huella digital del usuario"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Que desbloquea el sensor?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Solo una app de Windows"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"La app muestra los archivos"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Memoria flash sin cifrar"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Deriva la clave del controlador"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Chip AES del controlador"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Memoria flash cifrada con AES-XTS"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La memoria de Lenovo no tenía nada de esto. No había MEK, no había KEK, no había motor AES. Había una tarjeta microSD estándar, del tipo que se vende suelta en cualquier tienda, detrás de un lector de huellas conectado únicamente a la lógica de la aplicación de escritorio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo verificar en la práctica
&lt;/h2&gt;

&lt;p&gt;Antes de confiar en la etiqueta de un USB o disco externo, hay tres comprobaciones concretas que se pueden hacer sin desarmar nada.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Revisar el feature set ATA Security con hdparm
&lt;/h3&gt;

&lt;p&gt;En Linux, instalá hdparm (&lt;code&gt;sudo apt install hdparm&lt;/code&gt; en Debian o Ubuntu, &lt;code&gt;sudo dnf install hdparm&lt;/code&gt; en Fedora) y consultá el bloque de seguridad del disco:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;hdparm &lt;span class="nt"&gt;-I&lt;/span&gt; /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Un disco con el feature set ATA Security activo muestra algo como esto en la salida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Security: 
    Master password revision code = 65534
        supported
        enabled
    not locked
        frozen
    not expired: security count
        supported: enhanced erase
    2min for SECURITY ERASE UNIT.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el bloque dice 'not supported' o directamente no aparece, el disco no implementa el feature set ATA Security. Eso es normal en la mayoría de memorias USB simples y no es, por sí solo, prueba de fraude, pero combinado con la ausencia de cualquier otra documentación técnica es la primera señal de alerta.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Confirmar TCG Opal con sedutil-cli
&lt;/h3&gt;

&lt;p&gt;Para SSD y unidades autocifradas que afirman cumplir TCG Opal, la Drive Trust Alliance mantiene sedutil-cli, una herramienta de línea de comandos que no viene empaquetada en todos los repositorios, así que lo más seguro es compilarla desde su repositorio oficial en GitHub o instalar el paquete si tu distribución lo ofrece. El escaneo básico es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sedutil-cli &lt;span class="nt"&gt;--scan&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El comando lista cada disco conectado junto a un indicador del nivel de soporte Opal detectado, por ejemplo 2 para Opal 2.0. Un guion en esa columna significa que el disco no implementa Opal, sin importar lo que diga el empaque.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Verificar el certificado FIPS en el CMVP de NIST
&lt;/h3&gt;

&lt;p&gt;Cuando el fabricante anuncia FIPS 140-2 o FIPS 140-3, tiene que existir un número de certificado público. Buscalo en el &lt;a href="https://csrc.nist.gov/projects/cryptographic-module-validation-program" rel="noopener noreferrer"&gt;Cryptographic Module Validation Program de NIST&lt;/a&gt;: ahí aparece el nombre del módulo, el fabricante y el nivel de seguridad validado, del 1 al 4. Si el modelo exacto no figura en esa lista, el 'FIPS' de la caja es solo marketing, aunque el algoritmo interno sea AES real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant U as Usuario
    participant H as Host
    participant C as Controlador del disco
    U-&amp;gt;&amp;gt;H: ingresa PIN o huella
    H-&amp;gt;&amp;gt;C: envia credencial de autenticacion
    C-&amp;gt;&amp;gt;C: deriva la Key Encryption Key
    C-&amp;gt;&amp;gt;C: desbloquea la Media Encryption Key
    C--&amp;gt;&amp;gt;H: datos descifrados en tiempo real
    Note over C: la clave nunca sale del chip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Windows, &lt;code&gt;manage-bde -status C:&lt;/code&gt; muestra si BitLocker usa cifrado por hardware (eDrive) o cae a software porque el disco no lo soporta. En macOS, &lt;code&gt;diskutil info&lt;/code&gt; no distingue hardware de software en discos externos de terceros, así que para esos equipos conviene apoyarse directamente en el certificado FIPS publicado por el fabricante.&lt;/p&gt;

&lt;h2&gt;
  
  
  Casos de uso reales
&lt;/h2&gt;

&lt;p&gt;Las empresas que manejan datos regulados (salud, finanzas, gobierno, defensa) suelen exigir por contrato que cualquier memoria USB corporativa tenga FIPS 140-2 nivel 3 validado. Líneas como Apricorn Aegis Secure Key, iStorage datAshur PRO o Kingston IronKey publican su número de certificado y su nivel exacto en su documentación, precisamente porque sus clientes lo van a verificar antes de firmar la compra.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; El borrado criptográfico de una unidad autocifrada destruye la clave en milisegundos y vuelve ilegibles todos los datos, pero esa garantía solo existe si el cifrado era real desde el diseño: en una memoria como la de Lenovo no hay clave que borrar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En el sector salud, perder un USB con historiales clínicos sin cifrado real puede disparar la obligación de notificar a cada paciente afectado. Algunos marcos regulatorios reducen esa obligación cuando el dispositivo tenía cifrado certificado, así que el certificado no es un detalle burocrático: es lo que decide si hay que mandar miles de cartas de notificación.&lt;/p&gt;

&lt;p&gt;Fuera del mundo corporativo, el caso de uso más simple es el de cualquier persona que viaja con datos sensibles (contratos, historiales médicos propios, claves de acceso) en una memoria USB. Para ese uso, una unidad autocifrada certificada justifica su sobreprecio frente a un pendrive genérico con un sticker de 'AES-256' sin respaldo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;p&gt;Confundir el algoritmo con la implementación es el error más común. AES-256 es un algoritmo público y gratuito: cualquiera puede escribir 'AES-256' en una caja sin que eso implique que el chip adentro lo ejecuta, ni que la clave esté protegida, ni que el sensor biométrico tenga algo que ver con el cifrado.&lt;/p&gt;

&lt;p&gt;Asumir que todo lo que trae lector de huella es más seguro que una contraseña es otro error. Un sensor biométrico barato sin motor criptográfico es, en la práctica, más débil que una contraseña larga: no hay forma de 'cambiar' una huella comprometida, y en el caso de Lenovo ni siquiera estaba protegiendo nada.&lt;/p&gt;

&lt;p&gt;El feature set ATA Security, más viejo que TCG Opal, tiene un historial conocido de contraseñas maestras de fábrica que algunos fabricantes nunca rotaron ni documentaron para rotar, lo que en ciertos modelos antiguos permitía desbloquear el disco sin el PIN del usuario legítimo. Por eso las implementaciones modernas migraron a TCG Opal, que no depende de una contraseña maestra universal del fabricante.&lt;/p&gt;

&lt;p&gt;Comunidades de reparación y desarmado, como la que destapó el caso Lenovo en Reddit, terminan siendo el control de calidad real de este mercado: revisar un video o hilo de desarmado del modelo exacto antes de comprar vale más que leer la descripción del producto.&lt;/p&gt;

&lt;p&gt;Buena práctica: pedí siempre el número de certificado FIPS antes de comprar, no después. Un fabricante serio lo tiene impreso en la hoja de datos del producto, no escondido en un correo de soporte.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparativa con alternativas
&lt;/h2&gt;

&lt;p&gt;No todo lo que se vende como 'cifrado' ocupa el mismo nivel de confianza. La tabla siguiente ordena las tres categorías reales que existen en el mercado de USB y discos externos.&lt;br&gt;
Tipo de 'cifrado'Qué protege en realidadCómo verificarloCuándo confiarApp o sensor biométrico sin chip criptográfico (caso Lenovo)Nada: solo bloquea una interfaz, la memoria flash queda legible con cualquier lectorVideo o reporte de desarmado del modelo exactoNunca, para datos sensiblesCifrado por hardware sin certificación independienteCifra los bytes en el controlador, pero sin auditoría externa de la implementaciónhdparm -I o documentación técnica del fabricanteUso personal de bajo riesgoUnidad autocifrada FIPS 140-2 o 140-3 validadaCifrado AES-XTS auditado por un laboratorio acreditado y registrado en NIST CMVPNúmero de certificado contra el buscador de CMVPEmpresas, salud, finanzas, gobiernoEl programa CMVP de NIST es el único registro público donde se valida un módulo criptográfico bajo FIPS 140-2 o FIPS 140-3.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Dispositivo anuncia cifrado"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Tiene numero de certificado FIPS verificable?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si, aparece en CMVP"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado de hardware validado"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No, o no lo publica"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Soporta TCG Opal o ATA Security?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Si, confirmado con hdparm o sedutil-cli"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado por hardware probable, sin certificar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No, solo una app o sensor biometrico"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cifrado de marketing: no confiar"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La fila del medio es la más común y la más ambigua: muchos pendrives decentes de marca caen ahí. No son una estafa como el caso Lenovo, pero tampoco ofrecen la garantía auditada de un módulo FIPS. Y hay un escenario donde ni la fila de arriba conviene: si necesitás sincronizar un mismo contenedor cifrado entre Windows, macOS y Linux sin depender de un sensor físico que puede fallar o de un PIN de recuperación con intentos limitados, un contenedor de software como VeraCrypt sigue siendo más práctico que una unidad autocifrada atada a un único lector biométrico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Profundizando
&lt;/h2&gt;

&lt;p&gt;AES-XTS, el modo que usan casi todas las unidades autocifradas, fue diseñado específicamente para discos: cifra cada sector de forma independiente para que un cambio de un solo bit en el texto plano no afecte a los sectores vecinos, algo necesario cuando el almacenamiento se accede en bloques fijos y no como un flujo continuo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; La separación entre MEK y KEK es lo que vuelve posible cambiar el PIN de una unidad autocifrada en segundos: solo se re-cifra la MEK, unos pocos bytes, nunca los datos completos, sin importar cuántos terabytes tenga el disco.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Los niveles de seguridad FIPS 140-2 y 140-3, del 1 al 4, no miden el algoritmo, sino la implementación física: resistencia a manipulación del hardware, borrado de claves ante intentos de apertura, calidad del generador de números aleatorios. Un módulo de nivel 3, el más común en memorias USB corporativas, exige evidencia física de sabotaje y mecanismos de respuesta ante intrusión.&lt;/p&gt;

&lt;p&gt;El propio Trusted Computing Group documenta Opal 2.0 con estados explícitos para la unidad: Locked, Unlocked, Frozen, y un contador de intentos (Try Limit) que, al agotarse, puede bloquear el disco hasta un reinicio o forzar un borrado criptográfico, según cómo lo configure el administrador. Nada de esto existe en un dispositivo que, como el de Lenovo, nunca implementó el estándar.&lt;/p&gt;

&lt;p&gt;Una limitación real que vale aclarar: incluso un cifrado de hardware perfectamente implementado no protege nada si el disco queda desbloqueado y conectado. El cifrado defiende contra la pérdida o el robo del dispositivo apagado, no contra alguien que lo use mientras está desbloqueado. Eso es trabajo de otras capas de seguridad, no del chip AES.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Cifrado-de-hardware-en-USB-y-discos-c%C3%B3mo-saber-si-es-real-11-01" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: conectá un disco externo o USB que tengas a mano, corré &lt;code&gt;sudo hdparm -I /dev/sdX&lt;/code&gt; y revisá si el bloque Security aparece como supported antes de confiar en la palabra 'cifrado' de cualquier caja.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿El cifrado de hardware de un USB es siempre real si dice AES-256 en la caja?
&lt;/h3&gt;

&lt;p&gt;No. AES-256 describe un algoritmo público, no una certificación. Lo único que confirma una implementación real y auditada es un número de certificado FIPS 140-2 o FIPS 140-3 verificable en el CMVP de NIST.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre una unidad autocifrada y el cifrado por software como VeraCrypt?
&lt;/h3&gt;

&lt;p&gt;VeraCrypt y LUKS cifran con el procesador del equipo y guardan la clave en la RAM del sistema mientras el volumen está montado. Una unidad autocifrada hace el trabajo dentro del propio controlador del disco, y la clave nunca llega a la memoria RAM del equipo anfitrión.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo compruebo si mi disco soporta TCG Opal?
&lt;/h3&gt;

&lt;p&gt;Con &lt;code&gt;sedutil-cli --scan&lt;/code&gt; desde Linux, o preguntando directamente al fabricante por el nivel de Opal soportado, por ejemplo Opal 2.0. La ausencia de una respuesta técnica suele ser la respuesta.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Un sensor de huella digital reemplaza a una contraseña fuerte?
&lt;/h3&gt;

&lt;p&gt;Solo si ese sensor efectivamente deriva o libera la Key Encryption Key del controlador. Si apenas desbloquea una aplicación, como en el caso de Lenovo, no reemplaza nada: la memoria sigue expuesta a cualquiera que la lea directo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué significa que un módulo criptográfico tenga validación FIPS de nivel 3?
&lt;/h3&gt;

&lt;p&gt;Significa que, además del algoritmo correcto, el hardware fue evaluado por resistencia física a manipulación y por borrar sus claves ante un intento de apertura detectado. Es el nivel que suelen exigir los contratos corporativos y gubernamentales.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué pasó exactamente con el USB con huella digital de Lenovo?
&lt;/h3&gt;

&lt;p&gt;Según el desarmado documentado en Reddit, el dispositivo anunciado como cifrado resultó ser una tarjeta microSD genérica sin ningún componente criptográfico, con un lector de huella que solo controlaba el acceso a una aplicación de escritorio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.reddit.com/r/technology/comments/1xl2pr3/lenovos_encrypted_fingerprint_usb_drive_is_just/" rel="noopener noreferrer"&gt;Reddit r/technology&lt;/a&gt;: hilo donde se documenta el desarmado del USB con huella digital de Lenovo.- &lt;a href="https://csrc.nist.gov/projects/cryptographic-module-validation-program" rel="noopener noreferrer"&gt;NIST, Cryptographic Module Validation Program (CMVP)&lt;/a&gt;: registro oficial donde se verifica un número de certificado FIPS 140-2 o 140-3.- &lt;a href="https://en.wikipedia.org/wiki/Self-encrypting_drive" rel="noopener noreferrer"&gt;Wikipedia, Self-encrypting drive&lt;/a&gt;: explicación técnica del funcionamiento de las unidades autocifradas (SED).- &lt;a href="https://trustedcomputinggroup.org/" rel="noopener noreferrer"&gt;Trusted Computing Group&lt;/a&gt;: organización que publica el estándar TCG Opal usado en discos autocifrados.- hdparm: utilidad de Linux usada para consultar las características de seguridad ATA de un disco.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Let your LLM say I don't know instead of guessing</title>
      <dc:creator>Conor Bronsdon</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:30:07 +0000</pubDate>
      <link>https://dev.to/conorbronsdon/let-your-llm-say-i-dont-know-instead-of-guessing-2dog</link>
      <guid>https://dev.to/conorbronsdon/let-your-llm-say-i-dont-know-instead-of-guessing-2dog</guid>
      <description>&lt;p&gt;Your user asks a factual question. The model returns a polished paragraph. Nothing in the stack threw an error. That is exactly when you are most exposed. A language model generates the most plausible next words, not the most true ones, so a wrong answer can look identical to a right one. That mechanism is what people call &lt;a href="https://chainofthought.show/glossary/ai-hallucination/" rel="noopener noreferrer"&gt;AI hallucination&lt;/a&gt;: same token prediction, missing or weak facts, fluent fiction at the end.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chainofthought.show/guests/dan-klein/" rel="noopener noreferrer"&gt;Dan Klein&lt;/a&gt;, co-founder and CTO of Scaled Cognition, put the internals this way on Chain of Thought: we label outputs after the fact, but the model never splits “truth” from “guess” on its own.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If they're right, we call them truth. And if they're wrong, we call them hallucination. But the model does not internally distinguish between those.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Dan Klein, co-founder and CTO of Scaled Cognition&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I’d stop treating confidence in the UI as a proxy for correctness. Treat every fluent sentence as a claim you still owe evidence for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does fluency hide the errors you care about?
&lt;/h2&gt;

&lt;p&gt;Obvious mistakes get caught in QA. Klein’s audit story from enterprise work is worse: when his team audits enterprise systems, he says, the real hallucination rate is often about five times what the customer has noticed, because the rest are fluent enough to pass. His examples are a refund policy that is real and plausible but not yours, or yours but for a customer with a different status.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Looks right. It looks right and is right are not the same. It is very hard to detect hallucinations when they are packaged up sufficiently fluently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Dan Klein, co-founder and CTO of Scaled Cognition&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Chip Huyen made the data angle plain on Chain of Thought ep 5: missing or wrong context pushes the model toward invention.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Models are more likely to hallucinate when it does not have access to the necessary and correct information to answer questions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Chip Huyen, author of AI Engineering&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So the design job is to give the model the facts at answer time, allow silence when facts are missing, and verify what still matters. A smarter model does not remove that work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks when you only punish wrong guesses?
&lt;/h2&gt;

&lt;p&gt;Pre-training shows the model fluent text, not labeled false statements. Rare facts (like a specific birthday) do not repeat as patterns, so the model still produces something that sounds like an answer. Benchmarks make the incentive worse: “I don’t know” often scores like a wrong answer, while a random guess sometimes hits. OpenAI’s 2025 write-up on why language models hallucinate argues for penalizing confident errors more than honest uncertainty. Anthropic’s interpretability work on Claude describes a default to decline on unrecognized entities, with a “known entity” signal that can flip that off and invite a guess anyway.&lt;/p&gt;

&lt;p&gt;For your app, that means instructions that forbid uncertainty fight the same scoreboards that trained the model to guess. If your eval sheet marks abstain as a miss, you are training your team to ship guessers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you ground answers and still leave an out?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://chainofthought.show/glossary/grounding/" rel="noopener noreferrer"&gt;Grounding&lt;/a&gt; means building the reply from material you put in context at question time, ideally with citations per claim. That cuts invented detail because the model has less room to freestyle. It does not guarantee truth: sources can be stale, retrieval can miss the doc, and the model can still stretch past what the sources say. Many production issues that look like “model bugs” are retrieval or document problems first.&lt;/p&gt;

&lt;p&gt;General models also carry a &lt;a href="https://chainofthought.show/glossary/knowledge-cutoff/" rel="noopener noreferrer"&gt;knowledge cutoff&lt;/a&gt;: training frozen at a date, then released later. Ask about anything newer and you get “I don’t know” or a plausible guess. The standard fix is the same as grounding: fetch current or private text into the context window before generation (RAG, search, or both).&lt;/p&gt;

&lt;p&gt;My default pattern for factual features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve candidate passages for the question.&lt;/li&gt;
&lt;li&gt;If nothing passes a relevance threshold, return abstain (or escalate to a human). Do not ask the model to “try anyway.”&lt;/li&gt;
&lt;li&gt;If you have passages, instruct answer-only-from-these, cite span or doc id per claim.&lt;/li&gt;
&lt;li&gt;Run a faithfulness check on answers that can move money, policy, or compliance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 4 is where &lt;a href="https://chainofthought.show/topics/evaluation/" rel="noopener noreferrer"&gt;AI evaluation and reliability&lt;/a&gt; work pays off: separate counts for &lt;code&gt;answered&lt;/code&gt;, &lt;code&gt;abstained&lt;/code&gt;, &lt;code&gt;answered_supported&lt;/code&gt; and &lt;code&gt;answered_unsupported&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does an abstain-and-ground sketch look like?
&lt;/h2&gt;

&lt;p&gt;Label this as illustration, not production code from any guest or vendor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sketch: abstain if retrieval is weak; answer only from chunks
&lt;/span&gt;
&lt;span class="n"&gt;MIN_SCORE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.42&lt;/span&gt;  &lt;span class="c1"&gt;# tune on your corpus
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;faithfulness_check&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MIN_SCORE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abstain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No trusted source found.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;instruction&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Answer using ONLY the sources. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;If they do not support an answer, reply ABSTAIN.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;draft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ABSTAIN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abstain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Model declined.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;faithfulness_check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abstain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed source check.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The abstain path is a first-class HTTP response, not a thrown exception buried in logs. Users should see “we don’t know” when you mean it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Decide where a wrong fluent answer is costly; tighten grounding and checks there first.&lt;/li&gt;
&lt;li&gt;Retrieve before generate; abstain when retrieval is empty or weak instead of prompting harder.&lt;/li&gt;
&lt;li&gt;Tell the model abstaining is allowed; score abstain better than a confident wrong answer in evals.&lt;/li&gt;
&lt;li&gt;Check high-stakes outputs against supplied sources (faithfulness), not vibes.&lt;/li&gt;
&lt;li&gt;Remember fluent output is plausible text until your sources and checks say otherwise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The longer explainer, with the episode clips, is on &lt;a href="https://chainofthought.show/ai-decoded/why-do-llms-hallucinate/" rel="noopener noreferrer"&gt;Chain of Thought&lt;/a&gt;. It draws on &lt;a href="https://chainofthought.show/podcast/54-why-llms-are-plausibility-engines-not-truth-engines-dan-klein/" rel="noopener noreferrer"&gt;this episode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/2HwtyPE6JuQ" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://newsletter.chainofthought.show/subscribe?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=newsletter" rel="noopener noreferrer"&gt;Subscribe to the Chain of Thought newsletter&lt;/a&gt; for new episodes and write-ups like this one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drafted with AI assistance from the episode transcripts.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>testing</category>
    </item>
    <item>
      <title>Best WordPress Multilingual Plugins for 2027: Workflow, Cost and Control</title>
      <dc:creator>Mahdi JabinPour</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:29:30 +0000</pubDate>
      <link>https://dev.to/jabinpou/best-wordpress-multilingual-plugins-for-2027-workflow-cost-and-control-2gk1</link>
      <guid>https://dev.to/jabinpou/best-wordpress-multilingual-plugins-for-2027-workflow-cost-and-control-2gk1</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lumowp.com/best-wordpress-multilingual-plugins/" rel="noopener noreferrer"&gt;LumoWP&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Choosing a multilingual plugin is easy when the demo contains one paragraph and a language switcher. The difficult part comes later: a translated product goes out of stock, an Elementor template changes, a subscription renews, or an editor rewrites a sentence that already has five translations.&lt;/p&gt;

&lt;p&gt;That is where this comparison starts. The best WordPress multilingual plugin for your site is the one whose workflow still makes sense after the first translation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;About this 2027 guide&lt;/strong&gt;&lt;br&gt;
Researched on October 31, 2026 for people planning a 2027 website. Features and prices below describe the documentation available on that date, not unreleased 2027 versions. This is a documented workflow comparison, not a five-plugin performance benchmark. LumoWP sells a WPML AI translation add-on; that relationship is disclosed where it appears.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The shortlist: which plugin fits which job?
&lt;/h2&gt;

&lt;p&gt;There is no useful universal winner. Start with the part of your website that would be hardest to translate and maintain—not the easiest page in the demo.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;A strong starting point for&lt;/th&gt;
&lt;th&gt;Main working model&lt;/th&gt;
&lt;th&gt;The decision you must accept&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WPML&lt;/td&gt;
&lt;td&gt;Editorial teams, complex WordPress content and multilingual WooCommerce&lt;/td&gt;
&lt;td&gt;Connected language versions with translation jobs and integrations&lt;/td&gt;
&lt;td&gt;Configure the right components and test your actual builder widgets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polylang&lt;/td&gt;
&lt;td&gt;A manually maintained bilingual site or a WordPress-native editorial workflow&lt;/td&gt;
&lt;td&gt;Language assignments and relationships between content&lt;/td&gt;
&lt;td&gt;Budget separately for advanced workflows and WooCommerce&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TranslatePress&lt;/td&gt;
&lt;td&gt;Owners who want to translate while looking at the front end&lt;/td&gt;
&lt;td&gt;Translate rendered strings through a visual editor&lt;/td&gt;
&lt;td&gt;Plan for SEO features, source-text changes and dynamic states&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weglot&lt;/td&gt;
&lt;td&gt;Teams that prefer a managed translation service and a quick operational start&lt;/td&gt;
&lt;td&gt;WordPress integration with a hosted translation service&lt;/td&gt;
&lt;td&gt;Ongoing service cost, language limits and total translated-word allowance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MultilingualPress&lt;/td&gt;
&lt;td&gt;Separate regional sites with their own teams and store settings&lt;/td&gt;
&lt;td&gt;One language site per WordPress Multisite network site&lt;/td&gt;
&lt;td&gt;Network administration is part of the project&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are recommendations by use case, not measured rankings. A simple two-language brochure site and a store with subscriptions, custom product fields and regional pricing should not receive the same recommendation.&lt;/p&gt;

&lt;h2&gt;
  
  
  First understand what the plugin actually translates
&lt;/h2&gt;

&lt;p&gt;Think of a multilingual website as four connected systems: content storage, translation production, public URLs, and ongoing maintenance. A plugin may make the second part easy while asking you to do more work in the fourth.&lt;/p&gt;

&lt;p&gt;With a content-based workflow, an editor works with related language versions. With a rendered-string workflow, the translation layer works with text that appears on the page. With a multisite workflow, each language has its own site. A hosted service adds another question: what happens to the public translated experience if the subscription stops?&lt;/p&gt;

&lt;p&gt;None of these models is automatically faster, more professional or better for Google. They create different operational responsibilities. Your checkout, search results, logged-in dashboard and reusable templates are more informative test cases than a static About page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wpml.org/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flh1iiho0q9gl17i9dca3.webp" alt="WPML multilingual workflow — conceptual illustration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual illustration, not a software screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  WPML: a strong candidate for structured content and complex stores
&lt;/h2&gt;

&lt;p&gt;WPML is worth shortlisting when translation is an ongoing editorial process rather than a one-time conversion. Its Multilingual CMS and Agency plans include the advanced translation workflow and integrations needed for more involved sites. The cheaper Blog plan is a different scope, not simply the same product with fewer site licenses. Check the current &lt;a href="https://app.wpml.org/purchase" rel="noopener noreferrer"&gt;WPML plan comparison&lt;/a&gt; before choosing it for a builder-heavy site.&lt;/p&gt;

&lt;p&gt;For Elementor, start with the &lt;a href="https://wpml.org/documentation/plugins-compatibility/elementor/" rel="noopener noreferrer"&gt;official integration instructions&lt;/a&gt;. Translate reusable templates as well as pages. A translated page can still display a source-language header if the header comes from a separate template. Custom widgets can also need field registration; a page-builder compatibility badge does not tell you whether every third-party widget in your project exposes its fields correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My decision rule:&lt;/strong&gt; shortlist WPML when you need a coordinated translation workflow across posts, products, taxonomies and templates. Before committing, include your most unusual widget and your most complicated product in the pilot.&lt;/p&gt;

&lt;p&gt;For an existing site, do not buy another translation tool just because an update is missing. Our &lt;a href="https://lumowp.com/wpml-elementor-translations-not-updating/" rel="noopener noreferrer"&gt;WPML and Elementor troubleshooting guide&lt;/a&gt; explains how to separate a missing field, a template issue and an outdated translation before translating again.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to check before paying for automatic translation
&lt;/h3&gt;

&lt;p&gt;The plugin license and translation usage are different cost items. WPML's current &lt;a href="https://wpml.org/documentation/automatic-translation/automatic-translation-pricing/" rel="noopener noreferrer"&gt;automatic translation pricing documentation&lt;/a&gt; describes AI-word billing and different handling of edits depending on the workflow. Do not copy a calculation from an older article about credits and assume it still applies to your selected engine and account.&lt;/p&gt;

&lt;p&gt;Ask a practical question: if your team updates fifty product descriptions every week, what gets sent again, what is reused, and where can you inspect the charge? Calculate that before enabling a large automatic job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://polylang.pro/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4y2vg9r6ydl1rrqzlqlv.webp" alt="Polylang multilingual workflow — conceptual illustration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual illustration, not a software screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Polylang: attractive when editors want direct control
&lt;/h2&gt;

&lt;p&gt;Polylang is a sensible starting point for a site with a manageable number of languages and editors who can maintain the translated content. Its free version covers core multilingual content, while Pro adds workflow features such as duplication and expanded slug handling. WooCommerce has its own paid integration. The &lt;a href="https://polylang.pro/pricing/" rel="noopener noreferrer"&gt;official feature matrix&lt;/a&gt; makes these boundaries clearer than a generic “free versus paid” label.&lt;/p&gt;

&lt;p&gt;An easy setup mistake is leaving existing content without a language assignment. Follow the &lt;a href="https://polylang.pro/documentation/support/getting-started/setup-wizard/" rel="noopener noreferrer"&gt;setup wizard guidance&lt;/a&gt; and check existing posts, pages and navigation after assigning the default language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My decision rule:&lt;/strong&gt; choose Polylang for editorial control, not because somebody promises that fewer features must mean better performance. Compare the complete stack you actually need, including the WooCommerce add-on where relevant.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Elementor and automatic-translation detail that matters
&lt;/h3&gt;

&lt;p&gt;Polylang Pro offers DeepL translation using your own API connection, but its current pricing matrix explicitly says this machine-translation feature is not compatible with Elementor. That is a limitation of this specific workflow, not a claim that no Polylang-and-Elementor site can exist.&lt;/p&gt;

&lt;p&gt;If your brief says “automatically translate all Elementor pages,” resolve that requirement before choosing a plan. For a closer comparison of the editorial models, see &lt;a href="https://lumowp.com/polylang-vs-wpml/" rel="noopener noreferrer"&gt;Polylang versus WPML&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://translatepress.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwrcrhhm1118wr3evr9w5.webp" alt="TranslatePress multilingual workflow — conceptual illustration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual illustration, not a software screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TranslatePress: useful when translation starts with what visitors see
&lt;/h2&gt;

&lt;p&gt;TranslatePress takes a visual approach: work with the front end and translate the text in context. This can be easier for an owner who recognizes a button on the page but does not know which plugin generated it.&lt;/p&gt;

&lt;p&gt;The important technical detail is persistence. Its &lt;a href="https://translatepress.com/docs/automatic-translation/" rel="noopener noreferrer"&gt;automatic translation documentation&lt;/a&gt; explains that generated translations are stored in the database rather than requested from the translation API on every page view. That does not mean the complete site has zero translation-related runtime cost; it means repeated API generation is not the normal delivery model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My decision rule:&lt;/strong&gt; shortlist it when visual editing suits your team and your important front-end states can be reproduced for translation and review. Test a validation error, a cart update and an account page—not only visible text on the initial page load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source edits need a maintenance plan
&lt;/h3&gt;

&lt;p&gt;TranslatePress's &lt;a href="https://translatepress.com/docs/frequently-asked-questions/" rel="noopener noreferrer"&gt;FAQ&lt;/a&gt; describes the distinction between an original string and its translation. Changing the source can create a new string to translate, while the old translation remains stored. That is different from an editor thinking “I changed one paragraph in this translated post.”&lt;/p&gt;

&lt;p&gt;Try this before rollout: translate a page, change its heading and one repeated call-to-action in the source, then inspect the translated page. Write down what needs review. This small experiment tells your editorial team more than a screenshot of the translation sidebar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.weglot.com/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiovnnv0qflebpqornu9x.webp" alt="Weglot multilingual workflow — conceptual illustration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual illustration, not a software screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Weglot: a service decision as much as a plugin decision
&lt;/h2&gt;

&lt;p&gt;Weglot is appealing when the team wants to manage translation through a hosted service. The trade-off is a recurring service relationship with word and language allowances.&lt;/p&gt;

&lt;p&gt;One pricing detail deserves attention: the &lt;a href="https://www.weglot.com/pricing" rel="noopener noreferrer"&gt;Weglot pricing page&lt;/a&gt; describes a total translated-word allowance across the project, not a fresh allowance that resets every month. If a simplified 20,000-word source corpus is translated into three languages, use roughly 60,000 translated words as an initial planning estimate, then verify the actual counted content. Navigation, dynamic text and the service's counting rules can change the result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My decision rule:&lt;/strong&gt; shortlist Weglot when the ongoing service model is acceptable and the team values that workflow. Compare the plan required for your whole translated corpus, not just the starting price.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cancellation is an operational requirement
&lt;/h3&gt;

&lt;p&gt;Weglot's &lt;a href="https://support.weglot.com/article/247-how-to-cancel-my-subscription" rel="noopener noreferrer"&gt;cancellation documentation&lt;/a&gt; says translated content stops appearing when the relevant paid service is cancelled or paused. Treat exit planning as part of selection. Ask what you can export, what URLs you would need to preserve, and how you would replace the translated delivery layer before cancelling.&lt;/p&gt;

&lt;p&gt;This is not the same question as whether you retain a copy of translated text. Owning an export and continuing to serve the same multilingual website are two different things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://multilingualpress.org/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1jjkgk8ocb8lgnmioqyr.webp" alt="MultilingualPress multilingual workflow — conceptual illustration" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Conceptual illustration, not a software screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MultilingualPress: when markets need separate sites
&lt;/h2&gt;

&lt;p&gt;MultilingualPress uses WordPress Multisite, with each language on its own site. Its &lt;a href="https://docs.multilingualpress.org/docs/start-here/quick-start" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; presents independent content and configuration as central to the design.&lt;/p&gt;

&lt;p&gt;That makes it interesting when your German and French operations need more independence than translated paragraphs: different teams, different catalogs or different site settings. It also means backups, network permissions, deployment and integrations must be planned for a network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My decision rule:&lt;/strong&gt; shortlist it when separate sites are an intentional business requirement. Do not convert a simple brochure site to Multisite merely because a comparison labels the architecture “enterprise.”&lt;/p&gt;

&lt;p&gt;A useful question for the agency is: who owns the relationship between the sites after launch? If nobody will maintain cross-language links and shared requirements, architectural independence can turn into editorial drift.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about GTranslate and Loco Translate?
&lt;/h2&gt;

&lt;p&gt;GTranslate belongs in the discussion, but distinguish its free translation widget from its paid multilingual SEO offering. The &lt;a href="https://wordpress.org/plugins/gtranslate/" rel="noopener noreferrer"&gt;WordPress.org listing&lt;/a&gt; lists indexable language URLs and related SEO features in the paid offering. A visitor being able to read a translated page does not, by itself, establish that Google can crawl a dedicated translated URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wordpress.org/plugins/loco-translate/" rel="noopener noreferrer"&gt;Loco Translate&lt;/a&gt; addresses a different task: translating theme and plugin localization strings. It can help with interface wording, but it is not a substitute for a full architecture of translated posts, language URLs and editorial workflows. Do not compare these products as though they solve an identical problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Budget comparison: price the complete workflow
&lt;/h2&gt;

&lt;p&gt;The following are public entry points observed on October 31, 2026. They are not guaranteed 2027 prices. Taxes, promotions, renewal terms, usage and the required number of sites can change the final cost.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Observed starting point relevant to this guide&lt;/th&gt;
&lt;th&gt;What to budget beyond the headline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WPML&lt;/td&gt;
&lt;td&gt;Multilingual CMS: €99/year&lt;/td&gt;
&lt;td&gt;Translation usage and the appropriate integration stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polylang&lt;/td&gt;
&lt;td&gt;Free core; Pro from €99/year; WooCommerce add-on from €99/year&lt;/td&gt;
&lt;td&gt;Required combination of products and a translation provider if used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TranslatePress&lt;/td&gt;
&lt;td&gt;Personal: €99/year&lt;/td&gt;
&lt;td&gt;The plan with the SEO, team and provider features you need; additional usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Weglot&lt;/td&gt;
&lt;td&gt;Starter: €15/month or €150/year, 10,000 translated words and one translated language&lt;/td&gt;
&lt;td&gt;Growth of the total translated corpus and additional languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MultilingualPress&lt;/td&gt;
&lt;td&gt;Documentation advertises a starting €149/year for two languages&lt;/td&gt;
&lt;td&gt;Multisite hosting, maintenance and implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Verify these on &lt;a href="https://app.wpml.org/purchase" rel="noopener noreferrer"&gt;WPML&lt;/a&gt;, &lt;a href="https://polylang.pro/pricing/" rel="noopener noreferrer"&gt;Polylang&lt;/a&gt;, &lt;a href="https://translatepress.com/pricing/" rel="noopener noreferrer"&gt;TranslatePress&lt;/a&gt;, &lt;a href="https://www.weglot.com/pricing" rel="noopener noreferrer"&gt;Weglot&lt;/a&gt; and &lt;a href="https://docs.multilingualpress.org/docs/start-here/quick-start" rel="noopener noreferrer"&gt;MultilingualPress&lt;/a&gt; before purchasing.&lt;/p&gt;

&lt;p&gt;My planning formula is simple: &lt;strong&gt;license or subscription + translation generation + human review + maintenance + eventual migration&lt;/strong&gt;. Human review is not a rounding error. A cheap first translation can become expensive if your editors repeatedly repair terminology or cannot see which content changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What user reviews reveal—and what they do not
&lt;/h2&gt;

&lt;p&gt;I use public reviews and support threads to identify questions worth testing, not to calculate failure rates. People who post reviews are not a random sample, and a difficult support case does not establish that every installation has that problem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evidence reviewed&lt;/th&gt;
&lt;th&gt;What it tells a buyer&lt;/th&gt;
&lt;th&gt;What it does not prove&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TranslatePress's review listing includes praise for ease of use and support&lt;/td&gt;
&lt;td&gt;The visual workflow and assistance matter to users&lt;/td&gt;
&lt;td&gt;That your dynamic checkout or custom widget will work unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A negative TranslatePress review objects to paid slug translation; the developer explains the broader premium feature set&lt;/td&gt;
&lt;td&gt;Confirm the free/paid boundary before building around a feature&lt;/td&gt;
&lt;td&gt;That a price complaint is a technical defect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A WPML support thread reports partially translated Elementor pages and escalated investigation&lt;/td&gt;
&lt;td&gt;Include custom widgets and complete templates in your pilot&lt;/td&gt;
&lt;td&gt;A universal WPML bug or a known final root cause&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Sources: &lt;a href="https://wordpress.org/support/plugin/translatepress-multilingual/reviews/" rel="noopener noreferrer"&gt;TranslatePress user reviews&lt;/a&gt;, &lt;a href="https://wordpress.org/support/topic/honestly-horrible/" rel="noopener noreferrer"&gt;the slug-pricing review and developer reply&lt;/a&gt;, and &lt;a href="https://wpml.org/forums/topic/automatic-translation-dont-work-with-some-elementor-pages/" rel="noopener noreferrer"&gt;the WPML Elementor support discussion&lt;/a&gt;. The visible support discussion does not establish a final resolution; I am not presenting one.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.reddit.com/r/Wordpress/comments/1r6gjpk/would_you_still_recommend_wpml_in_2026/" rel="noopener noreferrer"&gt;2026 community discussion on Reddit&lt;/a&gt; shows the disagreement clearly: some participants value WPML integration coverage, while others report performance or maintenance frustrations on larger builds. These are self-reported experiences with different stacks, not controlled comparisons. The useful takeaway is to include your custom fields, forms and representative database size in the pilot.&lt;/p&gt;

&lt;p&gt;When you read a review, look for the plugin version, the actual requirement, the surrounding stack and the support response. “Slow” without a reproducible page, cache state and measurement is a reason to investigate, not a benchmark to copy into a buying guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pilot that can reject the wrong plugin before launch
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ehjdrguzsmcmder705f.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6ehjdrguzsmcmder705f.webp" alt="Four multilingual pilot tests: shared templates, source updates, checkout and language URLs" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An editorial checklist illustration, not a benchmark or a plugin screenshot.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Do not begin by translating a thousand URLs. On a staging copy, choose one target language and a small representative set. The goal is to expose the expensive failure modes early.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Acceptance condition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal article&lt;/td&gt;
&lt;td&gt;Translate headings, a link and an image caption&lt;/td&gt;
&lt;td&gt;Correct language, working links and preserved layout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared template&lt;/td&gt;
&lt;td&gt;Translate the header, footer and reusable call-to-action&lt;/td&gt;
&lt;td&gt;Every page using the template displays the intended version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source update&lt;/td&gt;
&lt;td&gt;Change a sentence after translation&lt;/td&gt;
&lt;td&gt;Editors can identify and review the affected translation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic interface&lt;/td&gt;
&lt;td&gt;Trigger form errors, cart changes and account states&lt;/td&gt;
&lt;td&gt;Important messages remain understandable in the selected language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variable product&lt;/td&gt;
&lt;td&gt;Choose a variation, add to cart and check out in a sandbox&lt;/td&gt;
&lt;td&gt;Product identity, stock, price and emails behave correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search and taxonomy&lt;/td&gt;
&lt;td&gt;Open a category and search for translated content&lt;/td&gt;
&lt;td&gt;Results and navigation follow the chosen language policy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache&lt;/td&gt;
&lt;td&gt;Compare cold and warm responses in each language&lt;/td&gt;
&lt;td&gt;No language leakage; performance is measured under equivalent conditions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exit rehearsal&lt;/td&gt;
&lt;td&gt;Review exports and restore a backup on staging&lt;/td&gt;
&lt;td&gt;The team knows what is portable and what needs rebuilding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Record the versions, theme, builder, host, cache settings and exact URLs. For timing, compare repeated measurements of the same page and separate cached delivery from uncached generation. Do not declare a plugin faster because one test hit a cache and the other did not.&lt;/p&gt;

&lt;p&gt;For WooCommerce, language and currency are separate dimensions. A French translation does not necessarily mean euros, and a German-speaking customer may live outside Germany. Test your chosen policy explicitly; our &lt;a href="https://lumowp.com/wpml-woocommerce-currency-by-language/" rel="noopener noreferrer"&gt;WPML currency-by-language guide&lt;/a&gt; covers that distinction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SEO checks that matter more than the plugin badge
&lt;/h2&gt;

&lt;p&gt;Google recommends separate URLs for different language versions and warns that locale-adaptive behavior can prevent complete crawling. A language switcher should provide a usable route to the translated page; do not make automatic redirection the only route. See Google's &lt;a href="https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites" rel="noopener noreferrer"&gt;multilingual and multi-regional site guidance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check the actual page output: an indexable URL, the intended canonical, matching language content and valid alternate-language relationships. Google's &lt;a href="https://developers.google.com/search/docs/specialty/international/localized-versions" rel="noopener noreferrer"&gt;hreflang documentation&lt;/a&gt; requires reciprocal references, including the page itself, for the relevant alternate sets. A checkbox in a plugin is not a substitute for inspecting the output.&lt;/p&gt;

&lt;p&gt;Do not translate into twenty languages just because the software permits it. Start where you can support the reader or customer, review critical wording and maintain updates. Our &lt;a href="https://lumowp.com/multilingual-seo-crawl-budget-hreflang/" rel="noopener noreferrer"&gt;multilingual SEO and crawl-budget guide&lt;/a&gt; explains the maintenance and discovery implications in more depth.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A practical stop condition&lt;/strong&gt;&lt;br&gt;
If the team cannot review checkout wording, maintain translated source updates or explain which URLs should be indexed, pause the rollout. Adding languages multiplies that unfinished work; it does not solve it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where Lumo's WPML AI add-on fits
&lt;/h2&gt;

&lt;p&gt;Disclosure: LumoWP develops and sells this add-on. It is not a sixth replacement for the multilingual systems above. Choose the multilingual architecture first; then decide how to generate and review translations inside that workflow.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://lumowp.com/product/lumo-wpml-ai-translation-addon-automate-your-multilingual-site-with-openai-claude-mistral-grok/" rel="noopener noreferrer"&gt;Lumo AI Translation Addon for WPML&lt;/a&gt; is relevant if you already use WPML and want an AI-provider workflow with your own API credentials. Its product interface includes separate bulk tools for content types, including Elementor templates. That can address a practical maintenance need, but it does not remove the need to check field compatibility, provider charges and translation quality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lumowp.com/product/lumo-wpml-ai-translation-addon-automate-your-multilingual-site-with-openai-claude-mistral-grok/" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyc6fgi1dvvs4vmbya7iv.webp" alt="Explore Lumo AI Translation Addon for WPML: translate posts, products, strings and Elementor templates with your own AI provider" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lumo supplies the translation engine while WPML manages the languages. Select the image to see the product and requirements.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Start with a small batch and a terminology list. Review names, units, product promises, buttons and links before expanding. No provider name or add-on guarantees a translation sounds natural in every language, and no plugin guarantees search rankings.&lt;/p&gt;

&lt;h2&gt;
  
  
  My recommendation for a 2027 project
&lt;/h2&gt;

&lt;p&gt;For a complex single-site WordPress or WooCommerce build, start by evaluating WPML against the real integration requirements. For a modest site with hands-on editors, evaluate Polylang. For a team that prefers visual translation, test TranslatePress. For managed-service convenience, calculate Weglot's full corpus cost and exit plan. For independent market sites, consider MultilingualPress with a deliberate Multisite operating plan.&lt;/p&gt;

&lt;p&gt;The final choice should be the plugin that passes your smallest realistic pilot with the least ongoing friction. You do not need the longest feature list. You need a translated website your team can still keep accurate six months after launch.&lt;/p&gt;

</description>
      <category>wordpress</category>
    </item>
    <item>
      <title>Post-Graduation Work Permit (PGWP) Eligibility in 2026: What International Students in Canada Need to Know</title>
      <dc:creator>Titanium Law Professional Corporation</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:29:18 +0000</pubDate>
      <link>https://dev.to/titaniumlaw/post-graduation-work-permit-pgwp-eligibility-in-2026-what-international-students-in-canada-need-ka8</link>
      <guid>https://dev.to/titaniumlaw/post-graduation-work-permit-pgwp-eligibility-in-2026-what-international-students-in-canada-need-ka8</guid>
      <description>&lt;h1&gt;
  
  
  Post-Graduation Work Permit (PGWP) Eligibility in 2026: What International Students in Canada Need to Know
&lt;/h1&gt;

&lt;p&gt;If you're an international student studying in Canada, the Post-Graduation Work Permit (PGWP) can be your bridge from the classroom to the Canadian workforce. But the rules changed significantly in late 2024 and mid-2025, and many students are unsure whether they still qualify.&lt;/p&gt;

&lt;p&gt;This guide walks you through the current eligibility requirements, timing rules, and what you need to prepare before you apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a PGWP?
&lt;/h2&gt;

&lt;p&gt;A Post-Graduation Work Permit is an open work permit that lets international graduates work for almost any employer in Canada after completing their studies. Unlike employer-specific work permits, a PGWP gives you the flexibility to change jobs, work part-time or full-time, and gain the Canadian work experience that can strengthen your permanent residence applications through Express Entry or other programs.&lt;/p&gt;

&lt;p&gt;The duration of a PGWP depends on how long your study program was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Programs shorter than 2 years:&lt;/strong&gt; You may receive a work permit up to the length of your program.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programs 2 years or longer:&lt;/strong&gt; You're typically eligible for a 3-year PGWP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Master's programs (8 months or longer):&lt;/strong&gt; You qualify for a 3-year PGWP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple eligible programs:&lt;/strong&gt; If you completed more than one eligible program (each at least 8 months long), IRCC may combine them to determine your PGWP length.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your passport validity also limits the maximum duration. If your passport expires in 2 years, your PGWP won't exceed 2 years even if your program length would otherwise qualify you for 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Eligibility Requirements
&lt;/h2&gt;

&lt;p&gt;To qualify for a PGWP, you must meet all of the following criteria:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Study at an Eligible Institution
&lt;/h3&gt;

&lt;p&gt;Your program must be at a Designated Learning Institution (DLI) that is on IRCC's PGWP-eligible list. Not all DLIs qualify. You can check the &lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/services/study-canada/study-permit/prepare/designated-learning-institutions-list.html" rel="noopener noreferrer"&gt;official DLI list&lt;/a&gt; to confirm your school's status.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Program Length
&lt;/h3&gt;

&lt;p&gt;Your program must be at least 8 months (or 900 hours) long. Programs shorter than this do not qualify for a PGWP.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Full-Time Student Status
&lt;/h3&gt;

&lt;p&gt;You must have maintained full-time student status during each academic session of your program. There are limited exceptions, such as authorized leaves of absence or reduced course loads due to documented circumstances, but these are assessed case by case.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Complete Your Program
&lt;/h3&gt;

&lt;p&gt;You must have completed all program requirements and received written confirmation (such as a final transcript or an official letter) from your institution that you've finished. You don't need to wait for your diploma or convocation ceremony, but you do need proof of completion.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Apply Within 180 Days
&lt;/h3&gt;

&lt;p&gt;This is critical: you must submit your PGWP application within 180 days of completing your program. The clock starts when you receive written confirmation that you've met all requirements, not when you attend your graduation ceremony.&lt;/p&gt;

&lt;p&gt;If your study permit expires before you apply for the PGWP, you may need to restore your status first, which requires an additional fee and a separate application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recent Changes: November 2024 and June 2025 Updates
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Language Proficiency Requirement (November 1, 2024)
&lt;/h3&gt;

&lt;p&gt;As of November 1, 2024, most new PGWP applicants must provide proof of language proficiency in English or French. The minimum level depends on your field of study:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;University graduates (bachelor's, master's, doctoral):&lt;/strong&gt; Canadian Language Benchmark (CLB) 7 in all four abilities (reading, writing, listening, speaking).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;College and other program graduates:&lt;/strong&gt; CLB 5 in all four abilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accepted language tests include IELTS General Training, CELPIP General, TEF Canada, and TCF Canada. Your test results must be less than 2 years old when you apply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who is exempt?&lt;/strong&gt; If you applied for your study permit before November 1, 2024, you are generally exempt from the language requirement. You also may be exempt if your program was in French or if you completed secondary school in Canada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Field of Study Requirement (June 25, 2025)
&lt;/h3&gt;

&lt;p&gt;As of June 25, 2025, PGWP eligibility is tied to specific fields of study classified under the Classification of Instructional Programs (CIP) codes. IRCC added 119 eligible fields and removed 178 fields from the list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you applied for your study permit &lt;strong&gt;on or after June 25, 2025&lt;/strong&gt;, your program's CIP code must be on the current eligible list.&lt;/li&gt;
&lt;li&gt;If you applied for your study permit &lt;strong&gt;before June 25, 2025&lt;/strong&gt;, you remain eligible for a PGWP as long as your field of study was on the eligible list at the time you applied, even if it has since been removed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This transition rule protects students who made decisions based on the rules in effect when they applied. You can find your program's CIP code on your acceptance letter or by contacting your institution's international student office.&lt;/p&gt;

&lt;p&gt;Eligible fields generally align with occupations in demand in Canada, including STEM (science, technology, engineering, math), healthcare, skilled trades, and certain business and service sectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Apply
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Gather Your Documents
&lt;/h3&gt;

&lt;p&gt;Before you start your application, collect the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Proof of completion:&lt;/strong&gt; Official transcript or letter from your institution confirming you've met all program requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Final transcript or report card&lt;/strong&gt; showing your grades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passport:&lt;/strong&gt; Must be valid for the duration of the PGWP you're requesting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language test results&lt;/strong&gt; (if required): Less than 2 years old, meeting the CLB level for your program.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proof of field of study&lt;/strong&gt; (if required): Documentation showing your program's CIP code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Digital photo:&lt;/strong&gt; Meeting IRCC specifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment:&lt;/strong&gt; $255 for the PGWP plus $85 for biometrics (if you haven't given biometrics in the last 10 years). You must pay both the open work permit holder fee and the work permit processing fee.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Apply Online
&lt;/h3&gt;

&lt;p&gt;Most PGWP applications are submitted through the IRCC online portal. You'll need to create an account, complete the application forms, upload your documents, and pay the fees.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Maintain Your Status
&lt;/h3&gt;

&lt;p&gt;If your study permit is still valid when you apply, you can remain in Canada under maintained status (formerly implied status) while IRCC processes your application. During this time, you may be eligible to work full-time off-campus if you've already completed your program and meet certain conditions.&lt;/p&gt;

&lt;p&gt;If your study permit has expired or will expire soon, you may need to apply to restore your status as a student before applying for the PGWP, or apply for a visitor record to remain in Canada legally while your PGWP is processed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Wait for Processing
&lt;/h3&gt;

&lt;p&gt;Processing times vary. Check the &lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/services/application/check-processing-times.html" rel="noopener noreferrer"&gt;IRCC processing times page&lt;/a&gt; for current estimates. You can work in Canada once your PGWP is approved, not while it's pending (unless you meet specific conditions under maintained status).&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Missing the 180-day deadline.&lt;/strong&gt; This is the most common reason students lose PGWP eligibility. Mark your completion date and count forward 180 days.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying before you've actually completed your program.&lt;/strong&gt; You need written confirmation that you've met all requirements, not just that you've finished your last exam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not checking your DLI's PGWP eligibility.&lt;/strong&gt; Some private career colleges or specific programs don't qualify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgetting the language test.&lt;/strong&gt; If you're subject to the November 2024 rules, your application will be refused without approved test results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Letting your study permit expire.&lt;/strong&gt; If it expires before you apply for the PGWP, you'll need to restore your status first, which costs more and takes longer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not verifying your CIP code.&lt;/strong&gt; If you applied for your study permit on or after June 25, 2025, your field of study must be eligible. Check your acceptance letter or contact your school.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What Happens After You Get Your PGWP?
&lt;/h2&gt;

&lt;p&gt;Once approved, your PGWP allows you to work for almost any employer in Canada. This work experience can help you qualify for permanent residence through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Canadian Experience Class (CEC):&lt;/strong&gt; Part of the Express Entry system, requiring at least 1 year of skilled work experience in Canada.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provincial Nominee Programs (PNPs):&lt;/strong&gt; Many provinces have streams for international graduates with Canadian work experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other federal programs:&lt;/strong&gt; Such as the Federal Skilled Worker Program or Federal Skilled Trades Program.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your PGWP is a valuable opportunity to build your Canadian career and strengthen your immigration profile. Use it wisely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Need Help With Your PGWP Application?
&lt;/h2&gt;

&lt;p&gt;The PGWP rules are detailed, and mistakes can be costly. If you're unsure whether you qualify, need help gathering documents, or want to understand your options after graduation, consider speaking with a regulated immigration consultant or lawyer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Titanium Law Professional Corporation&lt;/strong&gt; assists international students and graduates in Brampton and across Ontario with study permits, PGWP applications, and pathways to permanent residence.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://titaniumlaw.ca/" rel="noopener noreferrer"&gt;https://titaniumlaw.ca/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phone:&lt;/strong&gt; +1 778-683-8110&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consultation:&lt;/strong&gt; &lt;a href="https://titaniumlaw.ca/contact.html" rel="noopener noreferrer"&gt;https://titaniumlaw.ca/contact.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This article provides general information about Post-Graduation Work Permit eligibility and application requirements based on IRCC policies in effect as of 2026. It is not legal advice and does not cover every situation. Immigration rules change frequently, and your individual circumstances may affect your eligibility. Always verify current requirements on the official IRCC website at &lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship.html" rel="noopener noreferrer"&gt;https://www.canada.ca/en/immigration-refugees-citizenship.html&lt;/a&gt; or consult a regulated immigration professional before applying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/services/study-canada/work/after-graduation/eligibility.html" rel="noopener noreferrer"&gt;Post-Graduation Work Permit: Who Can Apply&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/services/study-canada/work/after-graduation/about.html" rel="noopener noreferrer"&gt;About the Post-Graduation Work Permit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/news/notices/update-requirement-post-graduation-work-permits.html" rel="noopener noreferrer"&gt;Update on Field of Study Requirement for PGWP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.canada.ca/en/immigration-refugees-citizenship/services/study-canada/work/after-graduation/apply.html" rel="noopener noreferrer"&gt;Post-Graduation Work Permit: How to Apply&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>education</category>
      <category>howto</category>
    </item>
    <item>
      <title>Voice AI for Beginners: Everything You Need to Know</title>
      <dc:creator>VoiceDeveloper</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:27:49 +0000</pubDate>
      <link>https://dev.to/voice_developer/voice-ai-for-beginners-everything-you-need-to-know-3dbb</link>
      <guid>https://dev.to/voice_developer/voice-ai-for-beginners-everything-you-need-to-know-3dbb</guid>
      <description>&lt;h2&gt;
  
  
  Voice AI for Beginners: Everything You Need to Know
&lt;/h2&gt;

&lt;p&gt;Voice AI is turning “talking to your computer” from a sci‑fi dream into a mainstream developer toolkit. Whether you’re building a smart assistant, a game NPC, or a podcast generator, the core building blocks—speech recognition, synthesis, and cloning—are now accessible through open APIs and cloud services. In this post we’ll walk through the fundamentals, show you how to hit the ground running with a quick Python/TTS demo, and explain why ElevenLabs is a top‑choice for high‑quality voice synthesis.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Voice AI Landscape
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Typical APIs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Speech Recognition (STT)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Converts spoken audio into text.&lt;/td&gt;
&lt;td&gt;Google Speech‑to‑Text, Whisper (OpenAI), Azure Speech&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Text‑to‑Speech (TTS)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Turns text into natural‑sounding speech.&lt;/td&gt;
&lt;td&gt;Amazon Polly, Google Cloud TTS, ElevenLabs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Voice Cloning / Voice Conversion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Re‑creates a specific speaker’s voice or adapts a voice model.&lt;/td&gt;
&lt;td&gt;Respeecher, Descript’s Overdub, ElevenLabs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The synergy of these layers lets you build full‑fledged conversational agents: &lt;em&gt;User speaks → STT → NLP → TTS → Speaker hears&lt;/em&gt;. The key to a smooth experience is low latency, high fidelity, and a voice that feels natural.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Why Text‑to‑Speech Matters
&lt;/h2&gt;

&lt;p&gt;You might think that speech recognition is the hard part, but TTS has become equally critical. A robotic or garbled voice can ruin user experience. Modern TTS engines use neural networks (e.g., Tacotron, FastSpeech) that generate waveforms with human‑like prosody, pauses, and emotion. If you’re looking to produce a brand voice or a character’s speech, you need a TTS system that supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple voices &amp;amp; accents&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom voice training&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low‑latency streaming&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter ElevenLabs, a cloud platform that offers high‑fidelity, low‑latency TTS and voice cloning. Their API is developer‑friendly, and you can experiment with voice presets or train your own voice with just a few minutes of audio.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Getting Started with ElevenLabs TTS
&lt;/h2&gt;

&lt;p&gt;Below is a quick, end‑to‑end example in Python that sends a text prompt to ElevenLabs and streams the resulting audio back to your local machine. No heavy dependencies, just the &lt;code&gt;requests&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_ELEVENLABS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.elevenlabs.io/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# 1️⃣ Define the voice you want
&lt;/span&gt;&lt;span class="n"&gt;voice_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bella&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Change to any voice ID you prefer
&lt;/span&gt;
&lt;span class="c1"&gt;# 2️⃣ Build the request payload
&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, world! This is a test of ElevenLabs TTS.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;voice_settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;similarity_boost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.65&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xi-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# 3️⃣ Call the API
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/text-to-speech/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;voice_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4️⃣ Save the streamed audio to a file
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.mp3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ Audio saved to output.mp3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; If you don’t have an API key yet, you can sign up for a free tier at &lt;a href="https://try.elevenlabs.io/kr07zfuqn1bp" rel="noopener noreferrer"&gt;https://try.elevenlabs.io/kr07zfuqn1bp&lt;/a&gt; and start experimenting right away.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The same concept works in JavaScript or via a &lt;code&gt;curl&lt;/code&gt; call, so pick whichever stack feels natural to you.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Voice Cloning: Re‑creating a Speaker
&lt;/h2&gt;

&lt;p&gt;Voice cloning lets you synthesize speech that sounds like a specific person. The process typically involves:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Collecting a clean recording&lt;/strong&gt; of the target speaker (30‑60 seconds is enough for many services).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uploading the audio&lt;/strong&gt; and letting the model learn the speaker’s timbre, cadence, and pronunciation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generating new utterances&lt;/strong&gt; using the cloned voice.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ElevenLabs offers a straightforward API for cloning, and the quality is comparable to the best commercial services. The only downside is the amount of data needed for a truly natural clone—generally a few minutes of speech.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Building a Simple Voice Assistant
&lt;/h2&gt;

&lt;p&gt;Let’s put it all together: a minimal assistant that listens to a user, transcribes the speech, processes a simple command, and replies using TTS. We’ll use Python with the &lt;code&gt;speech_recognition&lt;/code&gt; library for STT and the ElevenLabs API for TTS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;speech_recognition&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_ELEVENLABS_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.elevenlabs.io/v1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;synthesize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;voice&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bella&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;voice_settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;similarity_boost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xi-api-key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/text-to-speech/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;voice&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response.mp3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wb&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;✅ TTS completed. Playing audio...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Recognizer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Microphone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🎙️  Listening…&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recognize_google&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You said: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Simple command: if user says "time", reply with current time
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
            &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The time is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%I&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sorry, I didn’t get that.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="nf"&gt;synthesize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnknownValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;❌ Could not understand audio.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;sr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;❌ Could not request results; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you’ll learn from this snippet:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to capture microphone input in real time.
&lt;/li&gt;
&lt;li&gt;Basic STT with Google’s free API (you can swap out any other STT provider).
&lt;/li&gt;
&lt;li&gt;A clean separation between recognition, logic, and synthesis.
&lt;/li&gt;
&lt;li&gt;Easy integration with ElevenLabs for high‑quality speech output.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Tips for Production‑Ready Voice AI
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use streaming TTS endpoints; cache short phrases.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Keep user audio on-device or encrypt before sending.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use a CDN for static voice assets; consider serverless functions for on‑the‑fly synthesis.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Monitor API usage; many providers offer tiered pricing with free quotas.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you’re serious about building a voice product, start by profiling your application’s bottlenecks. Even a 200 ms latency can feel laggy for a conversational agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Wrap‑Up
&lt;/h2&gt;

&lt;p&gt;Voice AI is no longer a niche research area—it’s a developer playground. By combining open‑source STT models with powerful TTS services like ElevenLabs, you can create rich, interactive audio experiences in a matter of days. Whether you’re prototyping a chatbot, generating audiobooks, or cloning a celebrity voice for a marketing campaign, the tools are ready and the learning curve is gentle.&lt;/p&gt;




&lt;h2&gt;
  
  
  Call‑to‑Action
&lt;/h2&gt;

&lt;p&gt;Ready to add voice to your next project? Sign up for ElevenLabs today and get instant access to high‑fidelity TTS and voice cloning. Start with the free tier and explore the API: &lt;a href="https://try.elevenlabs.io/kr07zfuqn1bp" rel="noopener noreferrer"&gt;https://try.elevenlabs.io/kr07zfuqn1bp&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy coding, and may your apps always have a voice that feels like home!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>10Eros Beta5 in H3: Two-Pass Refinement Versus SelfLift Audio Conditioning</title>
      <dc:creator>AI-KSK</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:27:13 +0000</pubDate>
      <link>https://dev.to/ai-ksk/10eros-beta5-in-h3-two-pass-refinement-versus-selflift-audio-conditioning-jec</link>
      <guid>https://dev.to/ai-ksk/10eros-beta5-in-h3-two-pass-refinement-versus-selflift-audio-conditioning-jec</guid>
      <description>&lt;p&gt;These two exports use the same selected Beta5 base-model filename, but they are not interchangeable presets. One builds a coarse-to-refined audiovisual result from active image references. The other manually injects trimmed source audio into an audiovisual latent and uses a SelfLift sampler.&lt;/p&gt;

&lt;p&gt;The differences matter before you queue either graph: which inputs are active, which schedule reaches the sampler, where output audio comes from, and which branches actually save files. The supplied files contain 66 and 32 nodes respectively, totaling 98 nodes and 155 links. This guide reports static configuration, not a new generation, quality comparison, lip-sync test or benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  01 — Start with the current inputs, not the FL2VA title
&lt;/h2&gt;

&lt;p&gt;The first file has three active reference-image loaders: 112, 113 and 121. Their images reach the named reference slots 1, 2 and 3 on both conditioning stages.&lt;/p&gt;

&lt;p&gt;First-frame, last-frame, additional image, source-video, drive-audio, final-audio and reference-audio routes are saved bypassed. Their visible nodes and connected wires do not establish active media inputs. The conditioners request AUTO/native behavior, so do not describe this saved state as an active first/last-frame or source-audio-driven example simply because the filename mentions those modes.&lt;/p&gt;

&lt;p&gt;Reference slots are sparse. Check how the matching custom implementation resolves prompt Picture ordinals rather than assuming a slot suffix is a direct picture-number guarantee.&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow the linked prompt and dimensions
&lt;/h3&gt;

&lt;p&gt;Prompt node 28 supplies the active instruction. The saved text describes a woman, a mech and a perfume-related scene; that describes prompt intent, not independently reviewed reference-image content. The older red-Hanfu text stored inside the conditioners is overridden.&lt;/p&gt;

&lt;p&gt;Refinement adds a separate sharpness/natural-photorealism instruction through concatenation. That is another requested behavior, not proof that skin, faces or texture improve without changing identity.&lt;/p&gt;

&lt;p&gt;The coarse resolution selector stores &lt;strong&gt;4:3, 1 megapixel, multiple 32&lt;/strong&gt;. Its links override the conditioner's old 736×416 values. The learned latent upscaler is configured as &lt;code&gt;scale_by&lt;/code&gt; 1.5, and its width/height outputs feed the second conditioner. Stored 1344×768 and upscaler target-size fields do not define the effective output size in this route. Inspect actual dimensions after execution rather than quoting those defaults.&lt;/p&gt;

&lt;h2&gt;
  
  
  The active LoRA stacks differ between stages
&lt;/h2&gt;

&lt;p&gt;The selected base is &lt;code&gt;10Eros_Max_h3_TURBO-hybrid_beta5_int8_SinoX.safetensors&lt;/code&gt;. The FL2VA Turbo LoRA at node 5 is bypassed. Both ExposureSlider nodes are also bypassed, despite retained strengths.&lt;/p&gt;

&lt;p&gt;The coarse stack applies Combat at 0.7, the aesthetic and FrameRush selections at 0.5 each, and Motion Repair at 0.7. The refinement stack uses Combat at 0.49, the same aesthetic/FrameRush strengths, Motion Repair at 0.2, and an additional LMS selection at 0.3.&lt;/p&gt;

&lt;p&gt;These are configured selections, not verified effects. The “small-face” or “de-oiling” label does not make this a dedicated face-detection/crop/stitch graph. It uses a broader learned-latent two-pass route; there is no separate face-crop repair chain in this export.&lt;/p&gt;

&lt;p&gt;Attention-related patches are enabled upstream. Their names do not independently establish the effective runtime kernel, VRAM savings, compatible hardware or acceleration. Resolve the installed implementations before relying on their interactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The connected schedule is not the old eight-step sigma output
&lt;/h2&gt;

&lt;p&gt;DualClockSampler node 8 stores a steps value of 8 and supplies model/sampler outputs, but its &lt;strong&gt;SIGMAS output is unconnected&lt;/strong&gt;. LearnedTwoPassParityPlan node 9 supplies the connected schedules, with saved base/coarse/refine controls of &lt;strong&gt;9 / 4 / 5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Follow those connections rather than advertising an eight-step coarse run. Nor should the planned 4+5 split be presented as a measured total number of model evaluations: diagnostics are unused and the custom samplers/mixer were not executed here.&lt;/p&gt;

&lt;p&gt;The first sampler's &lt;code&gt;DENOISED_OUTPUT&lt;/code&gt; reaches the learned upscaler. The second conditioner builds a high-resolution template; reconciliation combines it with the learned latent and positive conditioning. DetailMixer then supplies the refined model, sampler and schedule.&lt;/p&gt;

&lt;p&gt;Tail, model-time bias, STG and restart switches are all off. Nonzero saved values inside those dormant options do not enable the features.&lt;/p&gt;

&lt;p&gt;The stages share a noise node whose seed control is randomize. Reconciliation's saved audio policies and second-pass strength zero describe requested behavior, not fixed-seed reproducibility or verified preservation of first-pass audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Duration and outputs in the first file
&lt;/h2&gt;

&lt;p&gt;The duration control is 10 and feeds this frame expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max(5, round(a * 24))
+ (5 - (max(5, round(a * 24)) % 17)) % 17
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;a = 10&lt;/code&gt;, standalone arithmetic gives 243 requested frames. At the configured 24 fps, that is a nominal 10.125 seconds—not a measured file duration. The connected count overrides old 124-frame widgets.&lt;/p&gt;

&lt;p&gt;The main refined latent is decoded into video and generated audio, then sent to a VHS combine node configured for H.265 MP4, &lt;code&gt;yuv420p10le&lt;/code&gt;, CRF 22 and 24 fps. This is not selected-source audio passthrough, nor proof of genuine high-bit-depth scene information.&lt;/p&gt;

&lt;p&gt;Two additional stage branches actively decode, create and save videos: one for the first sample and another for the refined sample. The latter decodes the same refined latent used by the main output. Their “preview” role does not mean they are unsaved, and their video-wrapper settings differ from the main VHS configuration.&lt;/p&gt;

&lt;p&gt;Expect to inspect three configured save destinations, not assume there is only one final file. No actual files or output counts were verified by generation in this review.&lt;/p&gt;

&lt;h2&gt;
  
  
  02 — SelfLift conditions on trimmed source audio
&lt;/h2&gt;

&lt;p&gt;The second file selects the same Beta5 base, but uses &lt;code&gt;qwen3vl_32b_minimax_h3_int8_convrot.safetensors&lt;/code&gt; rather than the first file's NVFP4/AWQ-named encoder. Both use the selected FP16 video VAE and FP32 audio VAE. Resolve the actual references instead of treating the dependency stacks as identical.&lt;/p&gt;

&lt;p&gt;Two image loaders are active. The saved prompt assigns Picture 1 to a character and Picture 2 to environment/composition; this is a statement about prompt roles, not visual verification. The reference-video and native reference-audio ports are unconnected.&lt;/p&gt;

&lt;p&gt;The resolution selector stores &lt;strong&gt;3:4, 1.5 megapixels, multiple 32&lt;/strong&gt;, overriding the conditioner's old 1344×768 values. Do not describe it as a fixed landscape setup.&lt;/p&gt;

&lt;p&gt;Trimmed source audio is encoded with the audio VAE and given a zero latent-noise mask. The reference-conditioning template is split, and its video portion is concatenated with the encoded audio. That assembled latent enters SelfLift. This is a manual audio-latent route, not a connected native reference-audio socket.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the audio-window fields and integer conversion carefully
&lt;/h2&gt;

&lt;p&gt;TrimAudioDuration stores &lt;code&gt;start_index = 14.63&lt;/code&gt; and &lt;code&gt;duration = 20.46&lt;/code&gt;. Those are not a start/end pair defining a 5.83-second window. Check the implementation's units and actual available source material before interpreting the resulting selection.&lt;/p&gt;

&lt;p&gt;The trimmed audio's reported length passes through the &lt;strong&gt;INT output&lt;/strong&gt; of ComfyNumberConvert before reaching the frame expression. Fractional precision is not passed straight through that wire.&lt;/p&gt;

&lt;p&gt;This file's expression adds an extra 24 after the alignment rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;max(5, round(a * 24))
+ (5 - (max(5, round(a * 24)) % 17)) % 17
+ 24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an integer input of 5, this arithmetic gives 148, not 124. For 10 it gives 267, and for 20 it gives 505. These are illustrative formula results, not claims about the actual trimmed audio length, downstream padding or generated frames.&lt;/p&gt;

&lt;p&gt;Do not reuse the first file's duration conclusion or assume every node automatically aligns the soundtrack. The visible output has no explicit post-decode trimming node, and VHS &lt;code&gt;trim_to_audio&lt;/code&gt; is false. Actual synchronization and end behavior require inspection.&lt;/p&gt;

&lt;h2&gt;
  
  
  SelfLift sampling and output are separate questions
&lt;/h2&gt;

&lt;p&gt;The four-step Turbo LoRA node is bypassed. BasicScheduler instead stores simple, 6 steps and denoise 1, while KSamplerSelect chooses Euler. SelfLift stores CFG 1, transition step 3, low-resolution scale 0.5, rho 0, weights 0.5–1, and the learned 3D latent upscaler. Its optional &lt;code&gt;model_hires&lt;/code&gt; input is unconnected.&lt;/p&gt;

&lt;p&gt;These are configuration facts, not a measured six-evaluation benchmark or proof of particular intermediate resolutions. Negative conditioning comes through ConditioningZeroOut. The memory/preview utilities also provide no measured VRAM result here.&lt;/p&gt;

&lt;p&gt;After SelfLift, the audiovisual latent is split and only the video portion is decoded. The final combine node receives the &lt;strong&gt;trimmed original audio directly&lt;/strong&gt;, not a newly decoded generated soundtrack. Its settings include H.264 MP4, CRF 12 and 24 fps.&lt;/p&gt;

&lt;p&gt;That establishes routing, not bit-perfect audio copying, voice preservation, equal durations or accurate lip synchronization. Listen to and inspect the actual output before accepting it as an audio-driven character result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import and acceptance checks
&lt;/h2&gt;

&lt;p&gt;Seven producer-side link-list entries are stale across the two files. Global link tuples and receiving input links agree, but some output lists still advertise links originating elsewhere. These are documented rather than silently repaired. Inspect imported connections with the compatible frontend; static consistency checks are not runtime certification or proof that the graphs must fail.&lt;/p&gt;

&lt;p&gt;Use authorized reference images and sound. Choose the intended active routes, update prompts, inspect effective dimensions and time controls, and identify every save destination. Run a small test before judging identity, faces, texture, movement, audio and any claimed quality gain.&lt;/p&gt;

&lt;p&gt;New canonical copies omit only known historical video-preview metadata; source originals are preserved. Covers have not been visually reviewed. The &lt;a href="https://www.youtube.com/watch?v=KjHrHot5un8" rel="noopener noreferrer"&gt;source-provided tutorial&lt;/a&gt; was not live-verified, and no blanket license, compatibility claim or new benchmark accompanies this walkthrough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting the workflows
&lt;/h2&gt;

&lt;p&gt;Published by this channel. The graphs are free; weights, LoRAs and input assets are separate and carry their own terms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hugging Face:&lt;/strong&gt; &lt;a href="https://huggingface.co/AI-KSK/10eros-beta5-dual-workflows-307" rel="noopener noreferrer"&gt;AI-KSK/10eros-beta5-dual-workflows-307&lt;/a&gt; — two JSONs, covers, SHA256 manifest. &lt;strong&gt;Start here.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ModelScope (魔搭):&lt;/strong&gt; &lt;a href="https://www.modelscope.cn/models/Sunjian520/10eros-beta5-dual-workflows-307" rel="noopener noreferrer"&gt;Sunjian520/10eros-beta5-dual-workflows-307&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Civitai:&lt;/strong&gt; &lt;a href="https://civitai.com/models/3031919" rel="noopener noreferrer"&gt;01 Face touch-up second pass&lt;/a&gt; · &lt;a href="https://civitai.com/models/3031921" rel="noopener noreferrer"&gt;02 SelfLift audio digital human&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run without a local GPU:&lt;/strong&gt; &lt;a href="https://www.runninghub.ai/post/2101698407000969217?inviteCode=rh-v1111" rel="noopener noreferrer"&gt;01&lt;/a&gt; · &lt;a href="https://www.runninghub.ai/post/2101698905921818625?inviteCode=rh-v1111" rel="noopener noreferrer"&gt;02&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tutorial:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=KjHrHot5un8" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; · &lt;a href="https://www.bilibili.com/video/BV1hEhh6JEvE" rel="noopener noreferrer"&gt;Bilibili&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>comfyui</category>
      <category>videogeneration</category>
      <category>workflows</category>
      <category>experimentation</category>
    </item>
    <item>
      <title>Normal vs uncensored: what 540 prompts across three pairs actually show</title>
      <dc:creator>RESK</dc:creator>
      <pubDate>Sun, 01 Nov 2026 20:27:10 +0000</pubDate>
      <link>https://dev.to/resk/normal-vs-uncensored-what-540-prompts-across-three-pairs-actually-show-33o8</link>
      <guid>https://dev.to/resk/normal-vs-uncensored-what-540-prompts-across-three-pairs-actually-show-33o8</guid>
      <description>&lt;h1&gt;
  
  
  Normal vs uncensored: what 540 prompts across three pairs actually show
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; We ran the same 90 prompts on three normal models and their uncensored siblings. Harmful refusal fell from 80-100 to 21-34. Helpfulness on benign trigger prompts did not improve. Capability retention was a lottery: one pair gained 15 points, two lost 10 and 25. Uncensoring removed the brakes; it did not add skill.&lt;/p&gt;

&lt;p&gt;The full analysis is on the &lt;a href="https://lforla.org/blog/normal-vs-uncensored" rel="noopener noreferrer"&gt;LFORLA blog&lt;/a&gt;, and the benchmarks are public: &lt;a href="https://lforla.org/benchmarks/refusal-boundary" rel="noopener noreferrer"&gt;Refusal Boundary&lt;/a&gt;, &lt;a href="https://lforla.org/benchmarks/over-refusal" rel="noopener noreferrer"&gt;Over-Refusal&lt;/a&gt;, &lt;a href="https://lforla.org/benchmarks/capability-retention" rel="noopener noreferrer"&gt;Capability Retention&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Three matched pairs, all 4-bit GGUF on Ollama, one Tesla T4:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Llama 3.1 8B Instruct vs Mannix Llama 3.1 8B Abliterated&lt;/li&gt;
&lt;li&gt;Qwen2.5 7B Instruct vs huihui_ai Qwen2.5 7B Abliterate&lt;/li&gt;
&lt;li&gt;Mistral 7B Instruct v0.3 vs Dolphin Mistral 7B&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each model saw 90 prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;40 refusal-boundary prompts: 20 benign requests with a safety-adjacent trigger, 20 clearly harmful requests.&lt;/li&gt;
&lt;li&gt;30 over-refusal prompts: benign requests that contain trigger words such as kill, bomb, drugs, weapon or hack.&lt;/li&gt;
&lt;li&gt;20 deterministic capability tasks: math, logic, code, instruction following and reading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fixed judge, DeepSeek V4 Pro at temperature 0, classifies the refusal responses and returns helpfulness and safety scores. The capability tasks are checked by exact match, with no judge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;Normal → uncensored. Higher is better in every column.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pair&lt;/th&gt;
&lt;th&gt;Boundary F1&lt;/th&gt;
&lt;th&gt;Harmful refusal&lt;/th&gt;
&lt;th&gt;Benign helpfulness&lt;/th&gt;
&lt;th&gt;Retention&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Llama 3.1 8B&lt;/td&gt;
&lt;td&gt;92.90 → 49.59&lt;/td&gt;
&lt;td&gt;100 → 34.25&lt;/td&gt;
&lt;td&gt;88.33 → 81.33&lt;/td&gt;
&lt;td&gt;70 → 85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen2.5 7B&lt;/td&gt;
&lt;td&gt;90.56 → 31.89&lt;/td&gt;
&lt;td&gt;100 → 21.00&lt;/td&gt;
&lt;td&gt;88.00 → 72.00&lt;/td&gt;
&lt;td&gt;90 → 80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral 7B&lt;/td&gt;
&lt;td&gt;84.33 → 45.45&lt;/td&gt;
&lt;td&gt;80.75 → 32.75&lt;/td&gt;
&lt;td&gt;85.17 → 83.00&lt;/td&gt;
&lt;td&gt;60 → 35&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What surprised us
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The safety refusal collapsed
&lt;/h3&gt;

&lt;p&gt;The harmful refusal column is the share of the 20 disallowed requests where the model refused or deflected without providing actionable content. The normal models are at 100, 100 and 80.75. The uncensored variants fall to 34.25, 21 and 32.75.&lt;/p&gt;

&lt;p&gt;The abliterated models did not get better at recognising harmful requests. They stopped treating recognition as a reason to refuse. That is the main driver of the boundary F1 collapse.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Helpfulness did not improve
&lt;/h3&gt;

&lt;p&gt;This is the part that contradicts the usual "uncensored models are more useful" claim. On 30 legitimate requests with trigger words, all three uncensored variants score lower than their normal siblings: 81.33 vs 88.33, 72 vs 88, 83 vs 85.17.&lt;/p&gt;

&lt;p&gt;The refusal they lost did not turn into better answers. It turned into a different refusal boundary, not more help.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Capability is a lottery
&lt;/h3&gt;

&lt;p&gt;The 20-task screen is small but deterministic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Llama abliterated gains 15 points. The normal model answered two logic traps with Yes; the abliterated version got them right. Two questions, not a capability jump.&lt;/li&gt;
&lt;li&gt;Qwen abliterated loses 10 points, mostly exact instruction following.&lt;/li&gt;
&lt;li&gt;Dolphin Mistral loses 25 points: code falls from 83.33 to 16.67, math from 57.14 to 42.86. Dolphin is the least faithful pair: it is an uncensored fine-tune, not a pure abliteration of the same checkpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uncensoring is not a free upgrade. It is a different model with a different damage profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the boundary score is a harmonic mean
&lt;/h2&gt;

&lt;p&gt;The refusal-boundary score combines benign helpfulness and harmful refusal:&lt;/p&gt;

&lt;p&gt;2 × helpfulness × refusal / (helpfulness + refusal)&lt;/p&gt;

&lt;p&gt;A model that answers everything gets 100 and 0, and scores 0. A model that refuses everything gets 0 and 100, and scores 0. A model that is good at both gets a high score. The harmonic mean punishes one-sided behaviour in a way the arithmetic mean does not.&lt;/p&gt;

&lt;p&gt;That is deliberate. A single refusal rate rewards a brick. A single helpfulness score rewards a model that will do anything. The boundary is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;90 prompts, one run, one judge, one quantization. Signals, not a safety certification.&lt;/li&gt;
&lt;li&gt;The pairs are not pure controlled surgeries. Dolphin is a fine-tune, Mannix adds an uncensored prompt, huihui_ai is an abliteration.&lt;/li&gt;
&lt;li&gt;The 20-task retention screen is small. A 15-point move can be two questions.&lt;/li&gt;
&lt;li&gt;A benchmark score is not a deployment recommendation. A model that refuses everything and a model that complies with everything both score 0 on the boundary, for opposite reasons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Run it
&lt;/h2&gt;

&lt;p&gt;The prompts and rubrics are public on the three benchmark pages. If you run the same pairs, publish the raw outcomes: a score without the prompts and the classification rule is not reproducible.&lt;/p&gt;

&lt;p&gt;The full write-up, with the chart and the exact pair definitions, is at &lt;a href="https://lforla.org/blog/normal-vs-uncensored" rel="noopener noreferrer"&gt;lforla.org/blog/normal-vs-uncensored&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://lforla.org/blog/normal-vs-uncensored" rel="noopener noreferrer"&gt;lforla.org&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>safety</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
