splitStatements() only knew 'strings' and "identifiers", so a DO block or function body ($$ ... ; ... $$) was cut at its inner semicolons and failed, and a quote inside a comment (-- don't) opened a string that never closed. It now also skips dollar-quoted bodies, E'...' strings with backslash escapes, and comments. It moves to SqlGuard so it is tested with the other checks. OccController::run() now catches Throwable, so an Error thrown by a command is logged and returned like an Exception instead of ending in an HTTP 500. Not changed on purpose: showing rows for statements with RETURNING or data-modifying CTEs, and failure handling in the Makefile release targets. Both came up in the same review but are unrelated to the security fixes in this release.
OCCWeb terminal (maintained fork)
A web terminal for admins to launch Nextcloud's occ commands
About this fork
The original Adphi/occweb was marked deprecated by its author and is unmaintained. This fork tracks fanategorius/occweb, which picked up compatibility maintenance where Adphi left off, and adds SQL query mode, security hardening (admin checks, CSRF/confirmation flows, transactional batches), and PHP 8.1+ compatibility fixes on top.
Credits
- Adphi/occweb — original author/project.
- fanategorius/occweb — the actively maintained fork this repo is based on and tracks.
- Git-Usr123/occweb — independent fork; the
OC::$server->getConfig()→OC::$server->get(\OCP\IConfig::class)fix inOccController.phpwas spotted there and backported here.
This tool is still not the right place for big/risky operations. It has no support for
asynchronous or long-running tasks — every command runs synchronously inside a single PHP
web request, so anything that takes a while (occ files:scan on a large instance, a Nextcloud
major-version occ upgrade, occ maintenance:mode --on workflows) can time out mid-operation
with no way to recover cleanly. Use a real shell (SSH + occ directly, or the guest-agent/
console) for major upgrades and other long-running or high-blast-radius operations; reserve
this terminal for routine day-to-day occ/SQL admin tasks. This issue
has background on why Nextcloud has no native async support for occ tasks.
Install
Running Nextcloud AIO (Docker)? See INSTALL-AIO.md instead — the app path and deploy steps differ from the generic instructions below.
No build step required (plain PHP + vanilla JS). Clone straight into the
target server's apps/ directory and run the install script:
Nextcloud requires the app's directory name to match its id (extended_occweb), so
clone into that name explicitly rather than the repo's own name:
cd /var/www/nextcloud/apps
git clone https://github.com/dillardblom/occweb.git extended_occweb
bash extended_occweb/install.sh
install.sh removes the dev/CI-only files that don't belong in a running
install (tests/, .travis.yml, phpunit*.xml, composer.json,
composer.lock, Makefile), chown -Rs the app directory to the web
server user, and runs occ app:enable. It assumes Nextcloud lives at
/var/www/nextcloud and the web server user is www-data; pass different
values as arguments if that's not the case:
bash extended_occweb/install.sh /path/to/nextcloud custom-web-user
occ app:enable takes care of registering the app's version correctly, so
none of the "Deploying updates" caveats below apply to a fresh install —
they only matter once the app is already enabled and you're updating it in
place.
Before installing, check your Nextcloud version against the range in
appinfo/info.xml (dependencies/nextcloud, currently min-version/
max-version) — occ app:enable refuses to enable an app outside that
range.
Note: install.sh deletes files that are tracked in git. If you plan to
keep this install up to date with git pull instead of re-cloning, be
aware that a future upstream change to one of the removed files could make
a plain git pull refuse to merge — it will tell you so, and you can
git checkout -- <file> to recover it if that happens.
SQL query mode
Type sql in the terminal to switch into SQL query mode and run raw SQL
statements directly against the Nextcloud database (admin only). Separate
statements with ;. Use Shift+Enter to add a new line and Enter to
run the whole block in a single request — this matters for scripts like
SET vars.x = 'value'; SELECT current_setting('vars.x');, since every
statement in one submission runs on the same database connection/session.
Type occ to switch back to the normal occ-command mode.
⚠️ There is no undo for DELETE/UPDATE statements — double check what
you are about to run, ideally against a non-critical row/user first.
⚠️ Warnings ⚠️
- The application is not a real interactive terminal and does not support long running tasks.
So if your instance is pretty big, commands like
occ files:scanwill time out and fail. - Do not use
occ maintenance:mode --on, obvious... - The
rename-userSQL template is best-effort only: renaming a Nextcloud username is not an officially supported operation. It updates the core tables it knows about (oc_users,oc_preferences,oc_group_user,oc_group_admin,oc_ldap_user_mapping,oc_share,oc_mounts,oc_storages), but does not touch app-specific tables (Talk, Calendar, Contacts, Mail, two-factor/WebAuthn, etc.). You must also manually rename the user's data directory on disk (data/<old> -> data/<new>) with the web server stopped or in maintenance mode, then runocc files:scan --all. Back up the database first and test on a non-critical account.
Deploying updates
After pulling/copying new code into nextcloud/apps/extended_occweb/, restart PHP so
the changes actually take effect. occ app:disable/app:enable is not
enough — it does not clear PHP's opcode cache, so a stale, cached version of
the code can keep running (routes silently 404ing is a typical symptom).
Restart the PHP process itself, for example:
sudo systemctl restart php8.3-fpm # adjust to your installed PHP version
sudo systemctl restart apache2 # if PHP runs as an Apache module instead
If you bump the <version> in appinfo/info.xml
Nextcloud tracks each app's installed version in its database (installed_version
in oc_appconfig) separately from the <version> in info.xml. If you edit
files in place (copy/git pull) instead of going through the app store or
occ upgrade, those two get out of sync — Nextcloud then treats the whole
instance as "needs upgrade" and blocks most occ commands behind the
CLI-upgrade wizard, even though nothing about Nextcloud core actually
changed. After bumping the version, sync it manually:
sudo -u www-data php /var/www/nextcloud/occ config:app:set extended_occweb installed_version --value="X.Y.Z"
(use the same X.Y.Z as the new <version>), then restart PHP as above.
This does not apply on a fresh occ app:enable install — that command sets
installed_version correctly on its own.
Compatibility matrix
max-version in appinfo/info.xml only ever reflects the highest version we've actually
tested (see the policy comment right above it) - this table is the actual history of what
was verified, so a rollback target is obvious if a newer major causes problems.
| occweb version | Tag | NC version tested | Result |
|---|---|---|---|
| 0.3.4 | v0.3.4 |
33.0.8 | ✅ Verified (nc01, 2026-09-25) |
| 0.3.4 | v0.3.4 |
34.0.4 | ❌ Blank terminal - global jQuery gone on NC34 (jQuery is not defined), then a 412 "CSRF check failed" on every ajax call once jQuery was vendored. Fixed in 0.3.5. |
| 0.3.5 | v0.3.5-nc34 |
34.0.4 | ✅ Verified (nc01, 2026-09-26) - vendors its own jQuery + sends the CSRF requesttoken header explicitly on every ajax call |
| 0.3.5 | v0.3.5-nc34 |
33.0.8 | ⚠️ Believed compatible (the 0.3.5 change is additive-only, nothing removed that NC30-33 depended on) but not re-verified - nc01 no longer runs NC33 to test against |
| 0.4.0 | (untagged) | 34.0.4 | ✅ Verified (nc01, 2026-09-26) - app id renamed occweb → extended_occweb (App Store prep), no functional changes to the 0.3.5 fixes otherwise |
| 0.4.1 | v0.4.1-nc34 |
34.0.4 | ✅ Verified (nc01, 2026-09-26) - code review fixes: correct jQuery .fail() signature, added a missing .fail() handler on the initial terminal-load request |
| 0.4.1 | v0.4.1-nc34 |
33.0.8 | ⚠️ Same caveat as 0.3.5/0.4.0 - not re-verified, no NC33 test environment available. Also unresolved: js/jquery.js now loads unconditionally on every supported version, even NC30-33 where core still provides jQuery - flagged in code review, needs an NC33 environment to confirm it's harmless there. |
| 0.4.2 | (untagged) | 32.0.15 | ✅ Verified (testbak/, 2026-09-27) - terminal loads and runs commands correctly. Confirms the suspected jQuery issue above: core still exposes a read-only window.$ getter here, so our vendored js/jquery.js throws TypeError: Cannot set property $ of #<Window> which has only a getter on load - a real, uncaught console exception, but harmless in practice since the app attaches via window.jQuery (still writable), not window.$. Fixed in 0.4.3. |
| 0.4.2 | (untagged) | 33.0.9 | ✅ Verified (testbak/, 2026-09-27) - same result as 32.0.15: functional, same harmless-but-real window.$ console exception. Fixed in 0.4.3. |
| 0.4.2 | (untagged) | 35.0.1 | ✅ Verified (testbak/, 2026-09-27) after a real fix: the bootstrap request 500'd with a PHP fatal, Declaration of OccOutput::setErrorOutput() must be compatible with ConsoleOutputInterface::setErrorOutput(): void - NC35 bundles a Symfony Console version whose interface now declares that return type. Fixed by adding : void to OccOutput::setErrorOutput() (lib/Controller/OccOutput.php), which is compatible with every earlier Symfony/NC version too. Confirmed clean afterwards: no console errors, no CSRF issues, terminal fully functional. |
| 0.4.3 | (untagged) | 32.0.15, 34.0.4 | ✅ Verified (testbak/, 2026-09-27) - templates/index.php now only loads js/jquery.js when \OCP\ServerVersion::getMajorVersion() >= 34, since core still provides a working jQuery on 32/33. Re-tested both sides of the boundary: NC32 loads no jquery.js request at all and has zero console errors; NC34 still loads it and still works, confirming no regression. |
min-version/max-version in appinfo/info.xml were updated from 30/34 to 32/35 on 2026-09-27 based on the above: 30/31 have never actually been tested (not even before the app-id rename) so claiming them was never justified once the testbak/-based verification policy existed, and 35 is now a genuinely verified (and fixed) target rather than a guess. 30/31 are also past Nextcloud's own currently-supported boundary as of 2026-09-18 (32-35 supported), which independently confirms 32 as the right floor.
If a future major breaks something, v0.3.4 is the last version confirmed working on NC33
and older - but a plain git checkout v0.3.4 is not a working rollback by itself. That
tag predates the app id rename (it still declares <id>occweb</id>), so checking it out
into an extended_occweb-named install just produces a broken id/directory mismatch. A
real rollback means disabling/removing extended_occweb and deploying v0.3.4 fresh under
an occweb-named directory instead, same as the original install steps above. This is one
of the items still deferred to when a proper test instance exists (see the code review
notes in git history around 0.4.1) - not yet written up in full.
TODOs:
See open issues
