nextcloud / nextcloud/passman

[SHARING] Credentials including URL are raising an Exception and corrupt the vault (data loss)

Open
#407 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
JavaScript
Stars
823
Forks
117
Avg merge
1d 21h
Merged PRs (30d)
8

Description

Bug report

Trying to share login credentials including a url makes passman throwing an excepetion becauses of:

SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Steps to reproduce

Bug is reproducible in the online demo (did it twice)

  1. Create credentials with Label: test, Username: test, Password: test & URL: https://www.google.de
  2. Try to share it with any user
Expected behaviour

User wich got selected for sharing the credentials with, should be able to use the credentials.

Actual behaviour
  1. Vault gets corrupted if you dont delete the complete dataset instantly. If you try to reopen the vault its not gonna work.
  2. Selected User gets request for accepting the share but its not gonna work because data is corrupted.
Configuration

Operating system: Windows 10, Fedora 26 (Client)

Browser: FireFox 58, latest Chrome (tried multiple Browsers)

Extensions that might cause interference: none

Passman version: 2.1.5

Operating system: Debian 9 (Server)

Web server: Apache 2.4.25

Database: MariaDB Ver 15.1 Distrib 10.1.26-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2

PHP version: PHP 7.0.19-1

cloud server: Nextcloud

cloud version: 12.0.3

Browser log
Browser log ``` PATCH https://host/index.php/apps/passman/api/v2/credentials/GUID 500 (Internal Server Error) (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 n @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:45 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 setTimeout (async) k.defer @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 $evalAsync @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 then @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 m @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 m.(anonymous function) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:100 updateCredential @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:101 (anonymous) @ share.js?v=90f886b7a637504e07a5ce000a974531-0:369 C_Promise.call_then @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:40 (anonymous) @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:352 C_Promise.call_then @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:40 revision_workload @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:284 setTimeout (async) (anonymous) @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:307 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 $apply @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:146 l @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:97 J @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:102 t.onload @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 XMLHttpRequest.send (async) (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 n @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:45 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 setTimeout (async) k.defer @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 $evalAsync @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 then @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 m @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 m.(anonymous function) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 getRevisions @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:171 promise_revisions_update @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:274 setTimeout (async) C_Promise @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:49 (anonymous) @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:346 C_Promise.call_then @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:40 (anonymous) @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:232 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 $apply @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:146 l @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:97 J @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:102 t.onload @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 XMLHttpRequest.send (async) (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 n @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 $apply @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:146 l @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:97 J @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:102 t.onload @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 XMLHttpRequest.send (async) (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:103 n @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $digest @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:142 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:45 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 setTimeout (async) k.defer @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:48 $evalAsync @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:130 then @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:131 m @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:96 m.(anonymous function) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:99 getCredential @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:111 promise_credential_update @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:213 setTimeout (async) C_Promise @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:49 promise_workload @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:325 setTimeout (async) C_Promise @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:49 reencryptCredential @ credentialservice.js?v=90f886b7a637504e07a5ce000a974531-0:358 (anonymous) @ share.js?v=90f886b7a637504e07a5ce000a974531-0:363 C_Promise.call_then @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:40 (anonymous) @ shareservice.js?v=90f886b7a637504e07a5ce000a974531-0:241 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:59 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:64 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:64 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:64 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:64 generate @ crypto_wrap.js?v=90f886b7a637504e07a5ce000a974531-0:64 (anonymous) @ shareservice.js?v=90f886b7a637504e07a5ce000a974531-0:239 setTimeout (async) C_Promise @ promise.js?v=90f886b7a637504e07a5ce000a974531-0:49 generateSharedKey @ shareservice.js?v=90f886b7a637504e07a5ce000a974531-0:236 $scope.applyShare @ share.js?v=90f886b7a637504e07a5ce000a974531-0:358 fn @ VM18867:4 b @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:126 e @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:276 $eval @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:145 $apply @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:146 (anonymous) @ angular.min.js?v=90f886b7a637504e07a5ce000a974531-0:276 dispatch @ core.js?v=90f886b7a637504e07a5ce000a974531-0:3 r.handle @ core.js?v=90f886b7a637504e07a5ce000a974531-0:3 ```
Cloud log
Cloud log
Doctrine\DBAL\Exception\DriverException: An exception occurred while executing 'UPDATE `oc_passman_credentials` SET `guid` = ?,`vault_id` = ?,`user_id` = ?,`label` = ?,`description` = ?,`created` = ?,`changed` = ?,`tags` = ?,`email` = ?,`username` = ?,`password` = ?,`url` = ?,`icon` = ?,`expire_time` = ?,`files` = ?,`custom_fields` = ?,`otp` = ?,`hidden` = ?,`delete_time` = ?,`shared_key` = ? WHERE `id` = ?' with params [DATA REMOVED]: SQLSTATE[42000]: Syntax error or access violation: 1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Maybe favicons should be stored in filesystem instead of database? Their size can vary very.

Thank you very much for making this very useful tool.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the sharing flow named in share.js, credentialservice.js, shareservice.js, and crypto_wrap.js, then reproduce the URL-sharing steps while checking the cloud log. Inspect the oc_passman_credentials UPDATE and its database schema around the reported row-size error. Done means sharing credentials with a URL completes without an exception or vault corruption and the recipient can use them.

Written by the indexing model from the issue text.

Assessment

Tech stack
angularjs, javascript, mariadb, php
Domain
api, backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.