* fix HID limits to support international keyboards
* add ja-JP keyboard
* increase limits on BLE HID device profile
---------
Co-authored-by: Štefan Croitoru <66339601+turbospok@users.noreply.github.com>
The app now lives in its own repository and is published in the Apps
Catalog, so it no longer needs to ship with the firmware:
https://github.com/kidbomb/flipper-ccid-app
It builds against the stock app SDK with no firmware-side support: the
USB layer moved into the app in #4407, and the app now carries its own
copy of the CCID class definitions.
That leaves the usb_ccid.h header export in targets/f7/api_symbols.csv
and targets/f18/api_symbols.csv without an in-tree user. They are kept
here because dropping them is a breaking API change; they can go at the
next major API version bump.
Co-authored-by: Filipe Rodrigues <filipepazrodrigues@gmail.com>
Up/Down (Min) and Left/Right (Max) already adjusted the jiggle interval, but
nothing on screen said so. Both rows now show arrow hints while the jiggler is
stopped, and only for presses that would actually change the value.
Co-authored-by: sequesters <agiryan@proton.me>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drop the unlshd-090 release entries and keep only post-090 work:
EMV poller TLV bounds (#1048), EMV .nfc loader bounds (#1056),
JS Runner moved to a .fap, and the Termux FAP-building doc.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs: add "Building FAPs on Android with Termux" guide
Documents how to run ufbt inside Termux on a stock Android phone and
build .fap applications on-device - no PC, proot or VM. Adapted with
permission from @CamsShaft's BUILD-FLIPPER-FAPS-IN-TERMUX (MIT), see
issue #1028, with these changes for this repo:
- Point ufbt at the Unleashed update index instead of the official SDK,
and warn that a plain `ufbt update` silently switches back to it.
- Make the toolchain wrapper loop idempotent and version-agnostic:
glob the gcc version directory instead of hardcoding 12.3.1, skip
already-wrapped .real payloads so re-running after a toolchain update
can't wrap a wrapper, and keep bin/python3 out of it (it points at
Termux's Bionic Python and must not go through glibc's linker).
- Replace the `ufbt launch` deploy step: Android doesn't expose USB
CDC-ACM device nodes to Termux, so it can't work unrooted. Copy the
.fap out via shared storage instead.
Linked from HowToBuild.md and the ReadMe.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* upd changelog: FAPs on Android with Termux doc
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* [NFC] Bound file-controlled lengths in the EMV .nfc loader
emv_load() used lengths straight from the file as write sizes into
fixed-size fields of a heap-allocated EmvApplication: three unbounded
strcpy()s from file strings, and PAN length/AID length read as uint32_t
then passed to flipper_format_read_hex() with no bound against pan[10]
and aid[16]. Opening a crafted .nfc corrupted the heap, and an oversized
pan_len also walked the render loops past the array.
The three read_string() results were discarded too, so a failed read
left the scratch FuriString holding the previous key's value for the
next strcpy(). Only reachable when a key is absent, which fails the load
anyway - but it fed the overflow above.
Bound every copy by its destination. Strings truncate: they are
cosmetic, and emv_save() writes the keys even for a card with no such
tag, so a nameless card must still load. Lengths reject: the AID goes
out verbatim in the SELECT APDU and both lengths bound render loops, so
a truncated value is worse than a failed load. Lengths are committed
only once their bytes are read.
Also in emv_save(), which had the same file-field-width mismatch in the
write direction: PIN try counter dereferenced a uint8_t field through a
uint32_t*, writing three neighbouring bytes into the file. Plus an
unused FuriString allocation.
Closes#1055
* upd changelog [ci skip]
---------
Co-authored-by: MX <10697207+xMasterX@users.noreply.github.com>
* [NFC] Bound card-controlled TLV lengths in the EMV poller
* [NFC] Bound the EMV parser where the values actually live
* [NFC] Bound the PDOL against what the poller can transmit
* [NFC] Keep cardholder names a card may legally send
* [NFC] Make rejected tags and truncated log records visible
Pushing straight to dev never worked: dev's push allowlist doesn't include
github-actions[bot], so the unlshd-090 run died on GH006 after doing all the
work. The bot can push its own branch, so the bump now lands as a PR from
ci/bump-issue-template-<tag> (force-pushed per tag, so a re-run refreshes the
open PR instead of stacking duplicates).
Also adds workflow_dispatch with a tag input to redo a release whose automatic
run failed, or to fix the dropdown at any other time. The release path keeps
its not-a-prerelease + unlshd-* gate; manual runs are checked by a new tag
validation step instead, since a typo would otherwise reach every bug reporter.
GITHUB_TOKEN events don't trigger workflows, so the PR gets no labeler or
template check of its own: the area/ci-build label is applied at creation and
the body already ticks the AI disclosure.
Needs "Allow GitHub Actions to create and approve pull requests" enabled. If
it isn't, the run fails naming that setting and links a compare URL for
opening the PR by hand -- the branch is pushed either way.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Willy-JL was renamed to @WillyJL, so the previous commit changed the
SLIX poller credit to a stale handle. Restore it and use the current
handle in the new NightStand Clock entry too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two release-090 changes were missing or understated in the changelog:
- The built-in Clock app was replaced by the NightStand Clock (alarm,
brightness control, nightlight, stopwatch, persisted settings) and was
not listed at all.
- The NFC Magic entry only covered the Gen2/Gen1 detection work, not the
2.0 magic Ultralight/NTAG (USCUID-UL) write/clone/wipe support.
Also fixes the @WillyJL credit to the actual handle, @Willy-JL.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* CLI: consistent quoted path handling for loader and Sub-GHz
Fix issue #4248 where CLI commands disagreed on how paths with spaces
must be quoted:
- loader open: strip quotes from the application argument path so
`loader open subghz "/ext/subghz/Some File.sub"` works (quotes were
previously left in the path string passed to the app).
- subghz tx_from_file / decode_raw / keystore path args: use
args_read_probably_quoted_string_and_trim (same as storage CLI).
- args_read_probably_quoted_string_and_trim: treat missing closing
quote as failure (FURI_STRING_FAILURE), not a bogus zero index.
- Unit tests for quoted path extraction.
storage CLI already used the quoted helper; infrared/lfrfid already did
for file paths. This aligns loader + subghz with that convention.
Fixes#4248
* fbt format
---------
Co-authored-by: drkemp187 <193144151+drkemp187@users.noreply.github.com>
Co-authored-by: Stefan <66339601+turbospok@users.noreply.github.com>
PR template: port the "No AI assistance" option and the "tick exactly one" note
from all-the-plugins (xMasterX/all-the-plugins#249) so the two repos agree, and
add a check that fails the PR unless exactly one of the three boxes is ticked.
The check needs no token and checks out nothing (`permissions: {}`), so plain
`pull_request` is safe for forks; `edited` is in the trigger list so fixing the
description re-runs it.
pr-build.yml: #1052 bound github.head_ref/ref_name to env, but the branch name
still reached a `run:` block through steps.vars.outputs.ref/.dist, which the
"Assemble PR report" step interpolated. A branch named `x$(id)` still executed
there. Bind those outputs to env as well, and reduce SAFE_REF to
[A-Za-z0-9._-] instead of only replacing '/', so the outputs are inert for
every consumer. Artifact names are unchanged for ordinary branch names.
Pin the two third-party actions to commits: dessant/lock-threads runs with
issues+pull-requests write, and a mutable tag can be repointed at any time.
* [NFC] Fix Type 4 Tag listener crashes on malformed NDEF write APDUs
While emulating a Type 4 Tag, type_4_tag_listener_iso_write() trusted the
reader-supplied Lc and NLEN, so four malformed UPDATE BINARY APDUs reached a
furi_check instead of an error status word:
00 D6 00 00 lc = 0 / data = NULL -> deref in bit_lib_bytes_to_num_be
00 D6 00 00 00 same, via the Le-only body
00 D6 00 00 01 AA lc -= write_len underflows size_t -> ~4 GB allocation
00 D6 00 00 02 FF FF NLEN never clamped -> ~128 KB transient allocation
Reject an APDU with no data field, clamp the NLEN bytes consumed to what the
reader actually sent, and bound the new length by ndef_max_len before it sizes
the array. The partial-NLEN write now merges into the current length the way
the read path already does, instead of zeroing the byte it did not cover.
Behaviour for a spec-compliant write (offset 0, Lc >= 2) is unchanged.
Closes#1050
* [NFC] Fix wrong parent protocol in Type 4 Tag listener assert
Copy-pasted from the SLIX listener: the Type 4 Tag listener sits on
ISO14443-4a, not ISO15693-3, so any debug build crashed as soon as Type 4 Tag
emulation received a frame. Release builds are unaffected (furi_assert is
compiled out).
* upd changelog
bit_lib_get_bits reads data[position/8 + 1] whenever position isn't
byte-aligned, even when all the requested bits live in the current byte.
When position/8 is the last byte of the buffer that's a one-byte
over-read. The extra byte only contributes bits that get shifted back
out, so the return value is unchanged and optimized builds often drop
the load, but at -O0 AddressSanitizer flags it and the access is still
out of bounds.
Skip the next-byte read when shift + length <= 8. This is the same fix
that already landed in fbtng-corelibs; lib/bit_lib here is an independent
copy that never picked it up, so the TODO FL-3534 comment is still here.
Signed-off-by: Cole Munz <colemunz@gmail.com>
eventLoop.timer(mode, interval) passes interval straight into
furi_ms_to_ticks() with no validation. For a periodic timer an interval
of 0 divides by zero in furi_event_loop_process_expired_timers()
(elapsed_time / timer->interval) and is counted as expired on every
event-loop pass, so a one-line script - eventLoop.timer("periodic", 0) -
pins the thread running the loop.
Reject interval <= 0 at the binding with a normal script-level error,
matching how the other js_app modules report bad arguments. The <= 0
check also covers negative values that would otherwise wrap to a huge
interval when cast to uint32_t.
Signed-off-by: Cole Munz <colemunz@gmail.com>
protocol_pyramid_add_wiegand_parity() computes the trailing odd-parity
bit with protocol_pyramid_get_parity(source + length / 2, ...). length is
a bit count (24), so source + length / 2 moves the pointer 12 bytes,
but wiegand[] in protocol_pyramid_encode() is 3 bytes. It should read
bits 12..23 of the same buffer.
So the parity bit we transmit comes from stack memory past wiegand[]
instead of the card number. Checked every 8-bit FC against every 16-bit
card number: the bit is wrong for essentially half of them, which a
reader that validates 26-bit Wiegand parity rejects. Our own decoder only
checks the CRC-8 and the format length, so reading a written card back
with a Flipper doesn't show it.
Give get_parity an explicit start position instead of doing pointer
arithmetic with a bit count. The even-parity call keeps reading bits
0..11 and is unchanged.
Signed-off-by: Cole Munz <colemunz@gmail.com>
protocol_pac_stanley_decode() fills an 8-byte asciiCardId[] and hands it
to hex_chars_to_uint8(), which takes no length and loops
while(*value_str && value_str[1]) - it stops at a terminator the buffer
doesn't have. So every successful decode reads asciiCardId[8] and [9] off
the end of the array, and if those two stack bytes happen to be hex
digits it also writes past protocol->data, which is 4 bytes.
Made the buffer 9 bytes and zeroed it. The loop still fills [0..7] and
the parse now stops after exactly 4 bytes, which is what
PAC_STANLEY_DECODED_DATA_SIZE expects.
Signed-off-by: Cole Munz <colemunz@gmail.com>
felica_poller_state_handler_list_system reads response_system_code->system_count
before checking whether felica_poller_list_system_code actually succeeded. That
function only writes the response pointer on success - on a timeout, a bad CRC,
or a response shorter than 13 bytes it returns an error and leaves the pointer
untouched. Since it's an uninitialized stack variable, every error path here
dereferences garbage.
This is the default path for Standard FeliCa cards, since auth is skipped by
default, so a weak read, a card pulled away mid-read, or an emulator that
doesn't answer Request System Code crashes the reader. That's the crash in
#4314.
Move the response handling inside the success branch, matching every other
handler in this file.
Signed-off-by: Cole Munz <colemunz@gmail.com>
infrared_common_decoder_alloc() sets protocol and level but leaves
timings_cnt uninitialized. Every caller allocs then resets, and for RC5
(the one protocol with preamble_mark == 0) the reset path reads
timings_cnt and feeds it to consume_samples() as a length before the
reset function zeroes it a few lines later. With a nonzero garbage value
that shifts the 6-element timings[] array out of bounds, both read and
write.
Separately, the bounds check in infrared_common_decode() compares
timings_cnt (an element count) against sizeof(decoder->timings) (24
bytes for six uint32_t), so it doesn't fire until 24 instead of 6.
Should be COUNT_OF.
Both come down to timings_cnt not being trustworthy; init it at alloc and
use the element count in the check.
Signed-off-by: Cole Munz <colemunz@gmail.com>
CodeQL runs are still reporting green, but every run carries a
failure-level annotation: "CodeQL Action major versions v1 and v2 have
been deprecated." It is running on a compatibility shim. Move all four
pins to v4, and bump checkout from v3 to v6 to match the rest of the
repo and clear the Node 20 deprecation warning. Drop
setup-python-dependencies, which the run log confirms has had no effect
since CodeQL 2.16. Add a concurrency group so back-to-back pushes to dev
no longer run several full firmware builds plus analyses at once.
pr-comment.yml trusted pr_number.txt from the report artifact and
validated it only as an integer. That artifact is written by a job that
checks out and runs the PR's own code, so both the comment body and its
destination were attacker-controlled: a malicious fork PR could make the
privileged commenter post arbitrary markdown onto any open thread in the
repo. Check the named PR's head SHA against the triggering run's
head_sha, which comes from the event payload and cannot be forged, and
refuse to comment on a mismatch.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Include documentation about caller thread context for GUI methods
* Add method for checking if view dispatcher id is already in use
* bump api
---------
Co-authored-by: Lofty Inclination <loftyinclination@outlook.com>
Co-authored-by: Stefan <66339601+turbospok@users.noreply.github.com>