| Age | Commit message (Collapse) | Author | Lines |
|
No page asked for with r= was cached, no slot held a head that does not
parse as cgit's, and the hook never met a cache root that was missing,
so ignoring r=, keeping an unreadable slot, or complaining without a
cache all passed.
|
|
|
|
run_action repeated harness.run line for line, and three comments only
labelled the sections below them.
|
|
Both say a change to the code they share belongs in both, but nothing
held them to it, so a fix made to one alone in a path the unit checks
do not reach would have gone unseen.
|
|
The fake HMAC returned 16 bytes, so the checks signed with signatures
half the real length, and a signature cut short passed. tohex's output
was never pinned either, so dropping its zero padding stayed
consistent with itself and passed.
|
|
A cookie_path other than / has to keep Secure but drop the __Host-
name, which a browser takes only for the whole host. Neither was
tried.
|
|
An expired session was only tried against validate_value, never sent
through a visit, and nothing sent a session under the plain cookie
name, which a sibling subdomain can set where it cannot set the
__Host- one.
|
|
The checks that a forged session is not taken for a signed-in visitor,
and that https brings no warning, would also have passed on the page
saying logins are unavailable.
|
|
crypt(3) answers nil for a kind of hash the system does not check, but
the stand-in never did, so a login that raised on it, or let it
through, passed.
|
|
The check was a negated test_cmp, which also passes when either file
is missing, and a changed chain does not prove the new layer was
written. The chain's last line now has to name a graph file that
exists and was not in the chain before the push.
|
|
scan-path finds such a repository by its .git and serves it at the
work tree's path, so the hook has to strip the /.git it runs in. Only
bare repositories were tried, and a hook that kept it passed.
|
|
Nothing ran the hook against a cache filled with remove-suffix=1, so
a hook that kept the .git on the url, and so dropped none of the pages
cgit had cached under the shorter one, passed.
|
|
The hook exists to feed the idle column, but nothing had cgit read an
age file, so a hook writing a date cgit cannot parse, or one at a path
cgit no longer reads, passed.
|
|
The header said a file the pusher cannot write stays as it was, but the
hook replaces it through mv, which needs only the directory, and with
stdin not a terminal mv does so without asking. That is the useful
behaviour, so the header now says so, and a test holds the hook to it.
Only a directory the pusher cannot write keeps the old file, which was
the one case tested.
|
|
A repository with no branches is meant to keep the date cgit already
had, and the hook writes through a temporary file that must not be
left beside the real one. Neither was checked.
|
|
No hook ran under a restrictive umask, so dropping the forced umask 022
passed, and the age file and the graph would then be unreadable to the
web server. Git alone writes the graph as -r-------- under umask 077.
core.sharedRepository was only tried as group, so the case folding and
the numeric modes went unchecked.
|
|
The cache hook's named url, no url and no access cases, the age hook's
missing directory and shared group, and the first commit-graph write
ran under sh alone, though the comment said every shell. The runs that
did loop over the shells ignored what the hook printed, which reaches
the pusher, so a hook that wrote to stderr or broke on a bashism under
dash alone could pass.
|
|
The checks that pages went had nothing proving they were there to begin
with, so they would pass with nothing removed if the scan list stopped
being written or two keys shared a slot. Nor did anything check that
the copy of the hook was pointed at the trash directory, and a renamed
line would have left it wiping the system's cache wherever the test
user can write it.
cached_requests read the lock and the scan list as if they were pages
and hid a failing dd. The test without access could not fail, since
nothing can be removed there and the scan list alone names a.git, so
it now compares the slots with the pristine copy.
|
|
Every account shared one hash, so the binding of a session to its
account's hash could not tell accounts apart, and an account_hash that
handed back the wrong account's hash passed.
|
|
A failed login on a page with no query of its own comes back as
?login=failed, the common case, but only the &login=failed form was
tried. A drop_failure_flag that handled the ampersand alone would have
lost the message and piled flags onto the way back, and passed.
|
|
Every post carried both fields, so the guards for a missing name or
password never ran. An unknown name was checked for the cookie and the
Location alone, so an extra header or body for it passed, and only the
wrong password case had its log line checked for the name and against
the password.
|
|
The cgit-level check accepted any line starting "[cgit] ", the prefix
of cgit's own messages too, as proof that the filter logged a missing
module. The guarded copy also kept the system secret path, so on a
host with luaossl and a readable secret but no luaposix the form would
be signed and the test would fail.
|
|
Only all four libraries missing at once was tried, and the script was
not reloaded after they went, so a require at load would not have
failed there. The protected visit passed on any error, a typo's nil
call included. A login never ran without a library, so a fallback that
skipped the mask, or one that let any password through when crypt was
missing, passed.
|
|
The quadratic trim takes 0.58 seconds for the 20,000 spaces the check
used under LuaJIT on an M-series Mac, against a threshold of half a
second over two calls, so a regression could pass on a slightly faster
core. At 100,000 spaces it takes about fifteen seconds and the linear
one under a millisecond, and each call is now timed on its own.
|
|
The exponent and leading separator cases carried a made-up signature,
which fails the check whatever the parsing does, so loosening the
expiry pattern or dropping its start anchor passed. Both are now built
from properly signed tokens.
|
|
auth-file.lua says group names match whatever their case, but both
fixture files spelt devs alike, so dropping either lowercasing passed.
No repository named two groups and no user sat in two, so reading only
the first group of a list, or only the last line that matched, passed
as well. A repository with no groups at all is a file variant matter,
and for the inline one the check only repeated the empty one.
|
|
The age fixture had one branch whose author and committer dates were
the same, and its only tag was lightweight on that commit. Sorting
oldest first, writing the author date or reading every ref rather than
the branches all passed, and the expected date came from the same
for-each-ref the hook runs. The dates now disagree on every one of
those points and the hook's answer is held to a literal date, under
every shell.
|
|
is_safe_redirect looked at the first two characters alone, so it
accepted https://evil.example/ and javascript:x. Neither could be
signed today only because cgit always signs a url that starts with
virtual-root, and nothing tested that. A target now has to start with
a single slash, which needs virtual-root to be a path for logins to
work, as it is by default.
|
|
The unit checks always took the harness stand-ins and the cgit-level
checks needed a module to be missing, so the real luaossl and luaposix
were never exercised anywhere. A misuse of their interfaces, or a login
through cgit that never worked, passed every run.
Where an interpreter has both libraries and its crypt(3) checks a
SHA-512 hash from openssl passwd, the unit checks run again against
them, adding the secret's mode. Where cgit's own Lua does, a login is
posted through cgit and the cookie it grants opens the repository. Both
skip where crypt checks no SHA-512 hash or the libraries are missing.
|
|
login() in the checks posts username and password under names of its
own, so renaming either field in the form broke every real login while
the suite passed.
|
|
Both shipped filters key their access lists by a repository's url, and
MANUAL says cgit hands that over, but nothing read the argument. Every
auth test served a repository whose url and name were the same, so a
cgit that passed repo.name, under which a url-keyed list matches
nothing and every protected repository goes public, passed.
|
|
Only a missing users file and a missing repos file were tried. A
missing groups file denies today, but a change returning nil there
would have made every protected repository public unnoticed. The repos
file's log line and a users file with no line that parses, which has
to turn a login down without spending crypt, went unchecked too.
|
|
constant_equals was only checked for its answers, on strings that
differ in one byte. Summing the plain differences instead of their
squares passed, which accepts any signature with the same byte sum, and
so did a plain == at the signature or the password check.
|
|
Nothing read the expiry signed into a granted session. validate_value
treats 0 as never expiring, so a login that signed its session with 0
passed, since the Max-Age the browser is told comes from set_cookie
alone. The expiry second itself is now held to be too late, with the
clock held still, as a comparison of < instead of <= passed too.
|
|
The only tampering tried was a flipped signature, a field swapped for
another and the binding, so a payload that left out the expiry, the
salt or the value still passed, and a captured session could have been
extended for ever.
|
|
Every check signed and verified under one pinned secret, so a sign()
that left the secret out of the HMAC key, which makes every cookie
forgeable, passed.
|
|
The checks replaced get_secret with a constant, so its success path
never ran, and the luaposix stand-in had no link or unlink and a umask
that ignored its argument. Dropping the tightened mask, which leaves
the secret readable by everyone under the usual 022, or accepting a
short secret, passed. The real get_secret now makes the secret in the
run's directory through stand-ins that behave like the calls they
replace, and the checks cover the mask and its restoration, the link
race, the temporary file, reuse and a secret written by hand.
|
|
test-auth.lua wrote its fixtures into whatever directory it was started
from, so a run by hand from the checkout left auth-users and its
siblings behind, and the checks assumed no auth-users-missing or
no-such-directory already sat there. It now refuses to run without a
directory, and t0505 hands each interpreter and variant a fresh one.
The interpreter and paths are expanded inside the test body rather than
pasted into it in single quotes, so a path holding a quote no longer
breaks the eval.
|
|
Nothing checked a deleted file, a change of mode, a binary file, a
submodule, a path, a range between two commits or the root commit on
the HTML page, nor the 404 a revision that is no commit gets. The first
checks were steps titled as actions that read one page in turn, so
each now fetches its own.
|
|
The MANUAL promises the blame and stats pages and says mailmap.file
and mailmap.blob are ignored, and none of it was tested. The summary,
where v2.11.1 fixed a mailmap crash, was never loaded, and neither was
a committer, a mailmap on another branch or the repository flag turning
the map on. The empty search checked only that nothing matched, and
one test appended to the shared config.
|
|
The ident said to follow the mailmap had no entry in it, and the
commit filter that takes a value when no trailer filter is set had no
test, nor did brackets without an address, a message of nothing but a
block and the repository flag turning the table on. One test appended
to the shared config, and seven read a page an earlier test fetched.
|
|
Every request viewed HEAD and every gitlink sat at the top level, so a
link read from the wrong revision's .gitmodules, or looked up by the
shown name rather than the full path, passed. The other url schemes,
the whole-component rule, the other forges, the templates that take
precedence and the submodule page had no test, and the gitlinks
pointed at the parent's own commit rather than one of subtarget's.
|
|
Each period check needed a single heading of the right shape, so a
wrong window or column count passed, and the weekly default had no
check. A request that straddles midnight is made again rather than
failing, since cgit reads the clock for itself and a new day can open a
new period. The absence checks gain a presence check on the same page.
|
|
The index and log checks were absence-only, so a page with no dates
passed, and date-format=local ran under UTC on a commit made at +0000,
where local time and the commit's own read the same. local-time, the
-local formats and the rule keeping a listed date on one line had no
test.
|
|
Only the class prefix was checked, and the fixture held nothing between
the two week cutoff and now, so a bucket bound that slipped or a date
past now shown as a negative age passed. Each tag sits in the upper
half of its bucket, which the bucket below takes if its bound slips.
|
|
A followed diff kept every path that started with the requested one,
so following small.c took small.cpp in as well. A path now has to be
the requested one or lie below it, as the pathspec of an unfollowed
diff matches.
|
|
No entry content was checked, so a wrong link, id or date passed, and
the path control looked at the status alone. A max-atom-items of 0 or
below, all=1 and the epoch an empty feed takes had no test. The xmllint
checks read a feed an earlier test left behind, which was another feed
whenever that test failed early.
|
|
No test fetched a signature within the size limit, so the status, the
headers that keep a browser from sniffing it and the body went
unchecked, as did the answer for a ref with none and the plain tar
signature a compressed tar falls back to.
|
|
The names on the links were checked but never requested back, and the
tests shared one repository whose refs each test added to, so a run of
a subset broke them. On a case-insensitive filesystem a loose V1.0 also
answered lookups for v1.0, so the case tests checked different tags
from one filesystem to another. The slash ref sat at master's tip,
where the commit compare could not tell it from the default branch.
|
|
Only the entry count and one file were checked, never the archive
itself. git's own writer at the same commit gives the same bytes, so
each format is held to it, which also proves the commit served. That
leaves unzip -t unused, which busybox may not have.
|